Преобразование Ruby к C#

Попробуйте переустановить PostgreSQL. См. Выпуск . Библиотека Postgis не загружена. Ошибка # 46358

brew update; brew reinstall postgresql;

Нет необходимости переустанавливать postgist, как предлагает сообщение, если вы не используете его.

7
задан flalar 13 April 2009 в 17:11
поделиться

3 ответа

Я совсем не знаю C #, поэтому все, что я говорю о C #, следует принимать с небольшим количеством соли. Однако я попытаюсь объяснить, что происходит в этом фрагменте кода Ruby.

class << Cache

В Ruby есть нечто, называемое синглтон-методами . Они не имеют ничего общего с шаблоном проектирования программного обеспечения Singleton, это просто методы, которые определены для одного и только одного объекта. Таким образом, вы можете иметь два экземпляра одного класса и добавлять методы к одному из этих двух объектов.

Существует два разных синтаксиса для одноэлементных методов. Одним из них является просто добавление имени метода к объекту, поэтому def foo.bar (baz) определит метод bar только для объекта foo . Другой метод называется , открывающий класс singleton , и он синтаксически похож на определение класса, потому что это также то, что происходит семантически: методы singleton фактически живут в невидимом классе, который вставляется между объектом и его фактическим класс в иерархии классов.

Этот синтаксис выглядит следующим образом: class << foo . Это открывает одноэлементный класс объекта foo , и каждый метод, определенный внутри этого тела класса, становится одноэлементным методом объекта foo .

Почему это используется здесь? Ну, Ruby - это чисто объектно-ориентированный язык, что означает, что все , включая классы, является объектом. Теперь, если методы могут быть добавлены к отдельным объектам, а классы являются объектами, это означает, что методы могут быть добавлены к отдельным классам. Другими словами, в Ruby нет необходимости в искусственном различении между обычными и статическими методами (которые, во всяком случае, являются мошенничеством: на самом деле это не методы, а прославленные процедуры). Что такое статический метод в C #, это просто обычный метод в одноэлементном классе объекта класса.

Все это просто длинный способ объяснить, что все определено между class << Cache и его соответствующим end становится static .

  STALE_REFRESH = 1
  STALE_CREATED = 2

В Ruby каждая переменная, которая начинается с заглавной буквы, на самом деле является константой. Однако в этом случае мы не будем переводить их как поля static const , а как перечисление , потому что именно так они используются.

  # Caches data received from a block
  #
  # The difference between this method and usual Cache.get
  # is following: this method caches data and allows user
  # to re-generate data when it is expired w/o running
  # data generation code more than once so dog-pile effect
  # won't bring our servers down
  #
  def smart_get(key, ttl = nil, generation_time = 30.seconds)

Этот метод имеет три параметра (четыре на самом деле, мы увидим точно , почему позже), два из них являются необязательными ( ttl и generation_time ). У них обоих есть значение по умолчанию, однако, в случае ttl значение по умолчанию на самом деле не используется, оно служит в качестве маркера, чтобы узнать, был ли передан аргумент или нет.

30.seconds - это расширение, которое библиотека ActiveSupport добавляет к классу Integer . На самом деле он ничего не делает, он просто возвращает self . В этом случае он используется только для того, чтобы сделать определение метода более читабельным. (Существуют другие методы, которые делают что-то более полезное, например, Integer # minutes , который возвращает self * 60 и Integer # hours и т. Д.) используйте это как указание, что тип параметра должен быть не int , а скорее System.TimeSpan .

    # Fallback to default caching approach if no ttl given
    return get(key) { yield } unless ttl

Он содержит несколько сложных конструкций Ruby. Начнем с самого простого: конечные условные модификаторы. Если условное тело содержит только одно выражение, то условное выражение может быть добавлено в конец выражения. Таким образом, вместо того чтобы сказать , если a> b, то foo end , вы также можете сказать foo, если a> b . Таким образом, приведенное выше эквивалентно , если только ttl не вернет get (key) {yield} end .

Следующее также легко: , если не является просто синтаксическим сахаром для если нет . Итак, мы сейчас находимся на , если не ttl, то return get (key) {yield} end

В-третьих, это система истинности Руби. В Ruby правда довольно проста. Фактически, Falseess довольно прост, и истина выпадает естественным образом: специальное ключевое слово false равно false, а специальное ключевое слово nil равно false, все остальное - правда. Таким образом, в этом случае условное значение будет только истинным, если ttl имеет значение false или nil . false не является ужасным разумным значением для промежутка времени, поэтому единственное интересное значение - nil . Фрагмент был бы более четко написан так: if ttl.nil? затем вернуть get (key) {yield} end . Поскольку значение по умолчанию для параметра ttl равно nil , это условие имеет значение true, если для ttl не передан аргумент. Так, условное выражение используется для определения количества аргументов, вызванных методом, что означает, что мы не собираемся переводить его как условное, а скорее как перегрузку метода.

Теперь перейдем к выходу . В Ruby каждый метод может принимать неявный блок кода в качестве аргумента. Вот почему я писал выше, что метод на самом деле принимает четыре аргумента, а не три. Блок кода - это просто анонимный фрагмент кода, который можно передать, сохранить в переменной и вызвать позже. Ruby наследует блоки от Smalltalk, но концепция восходит к 1958 году, к лямбда-выражениям Лиспа. При упоминании анонимных блоков кода, но по крайней мере сейчас, при упоминании лямбда-выражений, вы должны знать, как представить этот неявный четвертый параметр метода: тип делегата, более конкретно, a Func .

Итак, что же делает yield ? Он передает управление блоку. По сути, это просто очень удобный способ вызова блока, без необходимости явно сохранять его в переменной и затем вызывать его.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется строковой интерполяцией . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

что делает yield ? Он передает управление блоку. По сути, это просто очень удобный способ вызова блока без необходимости явно сохранять его в переменной и затем вызывать его.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

что делает yield ? Он передает управление блоку. По сути, это просто очень удобный способ вызова блока, без необходимости явно сохранять его в переменной и затем вызывать его.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется строковой интерполяцией . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

с выход делать? Он передает управление блоку. По сути, это просто очень удобный способ вызова блока, без необходимости явно сохранять его в переменной и затем вызывать его.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется строковой интерполяцией . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

с выход делать? Он передает управление блоку. Это в основном просто очень удобный способ вызова блока, без необходимости явно сохранять его в переменной и затем вызывать его.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

в основном это просто очень удобный способ вызова блока без необходимости явного сохранения его в переменной и последующего его вызова.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

в основном это просто очень удобный способ вызова блока без необходимости явного сохранения его в переменной и последующего его вызова.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

    # Create window for data refresh
    real_ttl = ttl + generation_time * 2
    stale_key = "#{key}.stale"

Этот синтаксис # {foo} называется интерполяцией строк . Это означает «заменить токен внутри строки любым результатом вычисления выражения между фигурными скобками». Это просто очень краткая версия String.Format () , и это именно то, на что мы собираемся ее перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, я не проверял это, я даже не знаю, является ли он синтаксически допустимым. Надеюсь, это поможет в любом случае.

именно это мы и собираемся перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, у меня нет проверил это, я даже не знаю, если это синтаксически допустимо. Надеюсь, это поможет в любом случае.

именно это мы и собираемся перевести.

    # Try to get data from memcache
    value = get(key)
    stale = get(stale_key)

    # If stale key has expired, it is time to re-generate our data
    unless stale
      put(stale_key, STALE_REFRESH, generation_time) # lock
      value = nil # force data re-generation
    end

    # If no data retrieved or data re-generation forced, re-generate data and reset stale key
    unless value
      value = yield
      put(key, value, real_ttl)
      put(stale_key, STALE_CREATED, ttl) # unlock
    end

    return value
  end
end

Это моя слабая попытка перевести версию Ruby на C #:

public class Cache<Tkey, Tvalue> {
    enum Stale { Refresh, Created }

    /* Caches data received from a delegate
     *
     * The difference between this method and usual Cache.get
     * is following: this method caches data and allows user
     * to re-generate data when it is expired w/o running
     * data generation code more than once so dog-pile effect
     * won't bring our servers down
    */
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, TimeSpan generationTime, Func<Tvalue> strategy)
    {
        // Create window for data refresh
        var realTtl = ttl + generationTime * 2;
        var staleKey = String.Format("{0}stale", key);

        // Try to get data from memcache
        var value = Get(key);
        var stale = Get(staleKey);

        // If stale key has expired, it is time to re-generate our data
        if (stale == null)
        {
            Put(staleKey, Stale.Refresh, generationTime); // lock
            value = null; // force data re-generation
        }

        // If no data retrieved or data re-generation forced, re-generate data and reset stale key
        if (value == null)
        {
            value = strategy();
            Put(key, value, realTtl);
            Put(staleKey, Stale.Created, ttl) // unlock
        }

        return value;
    }

    // Fallback to default caching approach if no ttl given
    public static Tvalue SmartGet(Tkey key, Func<Tvalue> strategy) => 
        Get(key, strategy);

    // Simulate default argument for generationTime
    // C# 4.0 has default arguments, so this wouldn't be needed.
    public static Tvalue SmartGet(Tkey key, TimeSpan ttl, Func<Tvalue> strategy) => 
        SmartGet(key, ttl, new TimeSpan(0, 0, 30), strategy);

    // Convenience overloads to allow calling it the same way as 
    // in Ruby, by just passing in the timespans as integers in 
    // seconds.
    public static Tvalue SmartGet(Tkey key, int ttl, int generationTime, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), new TimeSpan(0, 0, generationTime), strategy);

    public static Tvalue SmartGet(Tkey key, int ttl, Func<Tvalue> strategy) => 
        SmartGet(key, new TimeSpan(0, 0, ttl), strategy);
}

Обратите внимание, что я не знаю C #, я не знаю .NET, у меня нет проверил это, я даже не знаю, если это синтаксически допустимо. Надеюсь, это поможет в любом случае.

12
ответ дан 6 December 2019 в 08:45
поделиться

Похоже, этот код передается блоку для оценки, если кэш не содержит запрошенных данных ( yield - это то, как вы называете блок). Это довольно идиоматичный код ruby; Я не знаю, как (или даже если) вы могли бы «перевести это» на c #.

Найдите вариант использования, чтобы понять, что я имею в виду. Вы должны найти что-то неопределенно похожее на это:

x = smart_get([:foo,"bar"]) { call_expensive_operation_foo("bar") }

Лучше было бы выяснить, что вам нужно сделать, и написать что-то, что делает это de novo в c #, а не пытаться «переводить» с ruby.

5
ответ дан 6 December 2019 в 08:45
поделиться

Похоже, вы пытаетесь перенести memcache-client с Ruby на C #. Если это так, может быть проще использовать встроенную клиентскую реализацию C # memcache, например:

http://code.google.com/p/beitmemcached/

В любом случае, я в целом согласен с MarkusQ, что перевод с Язык более высокого уровня для языка более низкого уровня, вероятно, будет в целом менее продуктивным, чем просто переписывание идиоматическим образом для целевого языка. Прямой перевод с Ruby на C # в лучшем случае даст вам очень уродливый код.

Ключевое слово yield Ruby позволяет вам вызывать блок кода, который был передан в качестве неявно объявленного аргумента методу. Так, например, вы можете считать определение метода smart_get действительно похожим на:

def smart_get(key, ttl = nil, generation_time = 30.seconds, &block)

И когда вы вызываете smart_get как таковой:

x = smart_get("mykey", my_ttl) { do_some_operation_here }

Материал в фигурных скобках присваивается блоку переменных в расширенном определении выше. yield затем вызывает код в & block. Это грубое упрощение, но оно должно помочь вам получить общее представление.

Вернемся к вашему обращению. Упрощение, которое я только что сделал, не обязательно даст вам 100%, потому что, как только вы найдете способ перевода этого кода на C #, другой фрагмент кода нарушит ваш перевод. Например, предположим, что данный метод должен проверять блок:

def foo
   if block.arity == 0
      # No arguments passed, load defaults from config file and ignore call
   else
      yield
   end
end

И, конечно, поскольку лямбды-объекты в Ruby являются первоклассными объектами, вы можете столкнуться с кодом, подобным следующему:

foo = lambda { |a, b, c| a + b + c }   
# foo is now defined as a function that sums its three arguments

И тогда Бог поможет вам, если вы столкнетесь с кодом это определяет методы на лету, или (хуже переводчика) использует преимущества гибких классов Ruby:

class Foo
   def show
      puts "Foo"
   end
end

foo = Foo.new
foo.show   # prints "Foo"

class <&lt;foo; def show; puts "Bar";  end; end

foo.show  # prints "Bar"

Foo.new.show  # prints "Foo"

foo.show  # Still prints "Bar"

Так как каждый экземпляр каждого класса в Ruby может иметь свое собственное определение класса, я не совсем уверен, как вы могли бы портировать даже простые примеры на C # без причудливой гимнастики. В Ruby есть много этих функций, которые могут помешать простому переводу, поэтому я бы порекомендовал изучить то, что вы пытаетесь перенести, а затем повторить его с нуля.

4
ответ дан 6 December 2019 в 08:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: