2010-11-24 19 views
5

ejecutar hago esto mucho en javascriptRubí equivalente a una función javascript auto

some_var || some_var = function(){ return "blah"}(); 

Me pregunto cuál es el equivalente en Ruby podría ser por lo que puedo hacer

some_var ||= # sequence of operations 

edición

Me llamó la atención el Proc.new.call, pero también me encontré con esto en el código de alguien:

a ||= begin 
    # do some stuff 
    # return some stuff 
end 

¿Es esto funcionalmente equivalente al uso de un Proc.new.call ??

edit2 Las personas parecen estar confundidas en cuanto a lo que estoy tratando de lograr. Imagínese esto en javascript:

function someExpensiveFunction(){ 
    # do some really expensive stuff 
    return "some expensive calculations" 
} 

a || a = someExpensiveFunction(); 

establece Obviamente a una vez ... Las llamadas a funciones caro una vez ... En este caso no me importa acerca de alcance, sólo necesito mi valor de retorno como una secuencia de eventos calculada en lugar de un solo valor

estoy bastante seguro de que mi ejemplo anterior es equivalente a ||= begin; ... end; ...

+0

¿qué estás tratando de lograr exactamente? Ruby tiene un alcance de nivel de bloque, que es diferente del alcance léxico que tiene JavaScript. A menudo verá funciones anónimas en JS para evitar problemas de alcance. – Matt

+0

no me importa el alcance ...solo quiero una sintaxis limpia para establecer una variable usando || = que involucra varias líneas de código – brad

Respuesta

2

por su comentario:

no se preocupan por la determinación del alcance ... sólo quieren una sintaxis limpia para establecer una variable usando || = que involucra múltiples líneas de código

No estoy seguro de entender por qué sientes que tienes que usar || = y una lambda. Podría, por ejemplo, utilizar

if(some_var.nil?) 
    # do some stuff 
    some_var = result_of_doing_some_stuf 
end 

O, como lo pones en tu ejemplo:

a ||= begin 
    # do some stuff 
    # return some stuff 
end 

No es claro por qué debe utilizar un proc o lambda.

Pero si se empeñan en usar || = y lambdas, usted podría hacer:

calculate = lambda { 1 + 1 } 
some_var ||= calculate.call 
+0

en realidad estoy tratando de evitar Proc/lambda que se acaba de dar como un ejemplo y por eso lo mencioné. – brad

1
s = Proc.new { 5 + 5 }.call 
+0

Acabo de encontrar: 'a || = begin # algún código end' ¿Alguna vez has visto eso? Es equivalente? – brad

+0

una mierda, el formato no salió bien, voy a editar mi publicación – brad

0

yo no estaba seguro de qué parte usted está planteando en un principio. El || lógico afecta sus operaciones esperadas. En Ruby, el equivalente es:

somevar = "blah" unless somevar; 

Si somevar es un valor nulo o un valor de cambio falso "bla". Si somevar no es nulo o verdadero, la línea no se ejecuta. La acción opuesta sería:

somevar = "blah" if somevar; 

Eso sería asignar "bla" si somevar es verdad o no nula.

Ruby tiene características de lenguaje similares a la función autoejecutable, y muchas bibliotecas Javascript se han inspirado en esas características.

Consulte esta página para obtener más información:

http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html

La sección "Bloques y Iteradores" sería de interés aquí. También "Bloques para transacciones" y "Bloques pueden ser cierres".

Básicamente, el bloque Ruby y el lambda de rubí son lo más parecido a la función autoejecutable del Javascript.

+0

Entiendo lo que || = hace, quiero || = alguna_función – brad

+0

Ahora viendo tus más de 2 ediciones, está más claro lo que intentabas realizar. Ya has aceptado la respuesta, por lo que no intentaré editar esta. –

0

Puede hacerlo con bloques lambda

some_var ||= lambda { "something" }.call 

o

some_var ||= Proc.new { "something" }.call 

En auto JS ejecutar funciones se utilizan generalmente para evitar alcances contaminantes, por lo que se pueden utilizar variables locales internamente, pero no lo hacen exponerlos.Desafortunadamente, si se usan bloques en Ruby anteriores a 1.9, este no es el caso, donde los bloques no tienen su propio alcance.

# Ruby 1.8.7 
x = "some initial value" 
some_var ||= Proc.new { x = 10; x + 2 }.call #=> 12 
x #=> 10 

así que si ese es el caso, probablemente haya una mejor solución para lo que estás tratando de hacer. Ruby no es Javascript.}

EDIT: Lo siento, olvidé la definición de la variable en los ámbitos frente a la asignación de variables. fragmento actualizado para reflejar que

+0

Ruby 1.8.6 da x indefinido en su ejemplo de alcance de bloque anterior. Todo lo que he hecho o leído sobre Ruby sugiere que siempre debe ser compatible con el alcance del bloque. – Matt

+0

Sí, quise mostrar sombreado variable allí. Mira mi respuesta actualizada, tienes razón sobre el alcance del bloque. Me pregunto qué intenta hacer el OP con ese estilo de programación. – Chubas

+0

Todavía estoy confundido: no hay sombreado variable en el snipper anterior. De hecho, estás demostrando lo contrario. – Matt

0

que puede hacer:

def run 
    @a ||= begin 
    x = 1 + 1 
    puts "Calculated x" 
    x 
    end 
end 
puts "run = #{run}" # => Calculated x, run = 2 
puts "run = #{run}" # => run = 2 

O utilizar una lambda si quieres pasar una variable

def run 
    @a ||= lambda do |i| 
    x = i + i 
    puts "Calculated x" 
    x 
    end.call(1) 
end 
puts "run = #{run}" # => Calculated x, run = 2 
puts "run = #{run}" # => run = 2 

pero es menos mágico y más legible para utilizar un método si vas a llamar a la lambda inmediatamente

def calc(i) 
    x = i + i 
    puts "Calculated x" 
    x 
end 

def run 
    @a ||= calc(1) 
end 
puts "run = #{run}" # => Calculated x, run = 2 
puts "run = #{run}" # => run = 2 
0

La diferencia entre un bloque (comenzar ... finalizar) un proceso y una lambda es la forma en que retorna el mango. el regreso no está permitido en el bloque. Volver en un retorno Proc Del dónde se ha definido y volver en Lambda hacer lo que se espera

Así

def f() 
    a = Proc.new do 
      return 5 # exit from f 
     end.call 
    # never called 
    a+10 
end 

retornos 5 (y no 15)

def g() 
    a = lambda do 
     return 5 
    end.call 
    a+10 
end 

retornos 15 (como se esperaba)

y

def f() 
    a = begin 
     return 5 
    end 
    a+10 
end 

no compila.

Si no está usando return en su bloque, entonces puede usar begin ... do (me gusta por cierto).

Cuestiones relacionadas