In ruby, you can call the following code for printing "foo" in the console:
p "foo"
or
puts "foo"
And it prints "foo". In scala, I created this function:
def p(forPrint: Any): Unit = {
println(forPrint)
}
but it needs to be called like p("foo"). How can I write:
puts "foo"
and print in scala with such syntax?
Or, like if Array.map{} equal Array map{}
can i
"foo" p equal println("foo")
Given this method:
def p(forPrint: Any): Unit = println(forPrint)
It is not possible in Scala to call it like this:
p "foo"
You can only omit the parentheses when calling a method from an object. For example:
scala> println "foo" // doesn't work
<console>:1: error: ';' expected but string literal found.
println "foo"
^
scala> Console println "foo" // does work
foo
In the context of your example, you can place p in an object:
object Test {
def p(forPrint: Any): Unit = println(forPrint)
}
Test p "foo"
The reason you can call array toList, instead of array.toList, is that array is an object, with a method toList. p is a method with an argument "foo", which is not allowed without referencing an object explicitly.
Ruby's enforcement of brackets is extremely lax compared to other programming languages, so it has a syntax that's unusually sparse. This is why it's often a language of choice for writing configuration files, there's not much grit in the expression.
Technically p(x) is equivalent to p x in Ruby, but the same is not true in other languages.
As far as I can tell, you can't do this in Scala because the meaning is different.
Generally trying to force one language to behave like another creates a lot of unnecessary confusion. I'd do it the Scala way whenever possible.
Related
I will try to explain the problem with a simple example:
def enclose(x)
[x]
end
In my application, enclose does something more complex, but in essence it returns an array, the content of which is solely determined by the value of the parameter x. I could it use it like this:
foo = 'abcd'
....
foo = enclose(foo)
Now to my question: Is it possible to write a method enclose!, which simply replaces the parameter by its enclosed version, so that the example could be written as
foo = 'abcd'
....
enclose!(foo)
Since Ruby passes arguments by reference, I thought hat this could maybe be possible. The naive approach,
def enclose!(x)
x = [x]
end
does not work - I think this is because the assignment creates a new object and leaves the actual parameter untouched.
Is there way, that I can achieve my goal? I think in Smallalk, there would be a method become which would change the object identity, but I didn't find something similar in Ruby.
Since Ruby passes arguments by reference, I thought hat this could maybe be possible.
Ruby is pass-by-value, not pass-by-reference, which you have proven yourself, because otherwise your code would have worked.
I think in Smallalk, there would be a method become which would change the object identity, but I didn't find something similar in Ruby.
There isn't. Ruby has neither pass-by-reference nor become:, what you want simply isn't possible.
There's some other interesting posts about how ruby is pass by value, but the values are references.
What it boils down to is, you can modify the variable an object refers to, but you cannot change it to refer to another object.
> a = [1]
=> [1]
> def add_a(array)
> array << "a"
> end
=> :add_a
> add_a a
=> [1, "a"]
> a
=> [1, "a"]
There is a way to sort of accomplish what you are asking for but it's not quite pretty. Ruby has this concept of a binding (http://ruby-doc.org/core-2.2.0/Binding.html), which is like a CallContext in .NET.
You can do something like this:
def enclose(x)
[x]
end
def enclose!(x, binding)
eval("#{x} = [#{x}]", binding)
end
foo = 'abcd'
enclose!(:foo, binding)
=> ["abcd"]
In the script above, the :foo means you are passing the name of the variable, and the binding (context) where to find its value. Then you're dynamically calling eval to evaluate the assignment operation foo = [foo].
I looked through this code and found author passes params to block using []. I tryed it myself
my_proc = proc { |x| x + 1 }
a = 0
my_proc[a] # => 1
my_proc.call(a) # => 1
What is the difference between this two calls? Is this a syntax sugar?
Both ways are exactly the same and are aliases to each other. Thus, both variants call the same method which is not determined by any special syntax. It is basically defined as:
class Proc
def call(*args)
#...
end
alias [] call
end
You might be interested to note that there is even a third way:
my_proc.(a)
This is actually syntactic sugar (i.e. is an extension of the syntax of the Ruby language language). All objects accepting #call can be "called" that way and Ruby ensures to invoke the call method.
They are functionally identical. You can use whichever style you prefer.
Can I some how pass the result of an evaluated block as an argument to a function?
This illustrates what I want to do by using a helper function (do_yield):
#!/usr/bin/env ruby
def do_yield
yield
end
def foo a
#'a' must be an array
puts "A: [#{a.join(", ")}]"
end
foo (do_yield{
a = []
a << 1
})
Can I do this without creating my own helper function? Preferably by using facilities in the language, if the language does not offer a way to do it, then is there an existing function I can use instead of my own do_yield
So, you want to pass a result of executing some code into some other code? You just need to convert your "block" to an expression (by making it a proper method, for example)
def bar
a = []
a << 1
end
foo bar
If your code is really this simple (create array and append element), you can use the code grouping constructs (which combine several statements/expressions into one expression)
foo((a = []; a << 1))
or
foo(begin
a = []
a << 1
end)
Personally, I'd definitely go with the method. Much simpler to read.
The piece of terminology you probably want to search for here is lambda - a lambda being an anonymous function that can be passed around as a parameter.
So to do what you are describing with a Lambda you might do this:
my_lambda = lambda do
a = []
a << 1
end
def foo a
#'a' must be an array
puts "A: [#{a.join(", ")}]"
end
foo my_lambda.call
Of course you can have parameterised lambdas and if foo was expecting a lambda you could have it call #{a.call.join(", ")}] ( your actual code has double-quotes everywhere so not sure it would work ) so that the evaluation only happened when it was passed.
This is an interesting and powerful part of Ruby so it is worth learning about.
I know that this code may be not quite correct:
def print_string(&str)
puts str
end
print_string{"Abder-Rahman"}
But, when I run it, this is what I get:
#<Proc:0x03e25d98#r.rb:5>
What is this output?
That's the default string representation of a Proc object. Because "Abder-Rahman" is in braces, Ruby thinks you're defining a block. Did you mean to put str.call inside of your function definition? That should call your block and return the string expression you defined inside it.
The problem is that you've declared that the "print_string" method takes a block argument (confusingly named "str") and you simply print the proc itself. You'd probably like to call the given procedure to see the string value it returns:
def call_proc(&proc)
proc.call
end
call_proc { 'Foobar' }
# => "Foobar"
What you've discovered is the syntax sugar that if you decorate the last argument of a method definition with an ampersand & then it will be bound to the block argument to the method call. An alternative way of accomplishing the same task is as follows:
def call_proc2
yield if block_given?
end
call_proc2 { 'Example' }
# => 'Example'
Note also that procedures can be handled directly as objects by using Proc objects (or the "lambda" alias for the Proc constructor):
p1 = Proc.new { 'Foo' }
p1.call # => "Foo"
p2 = lambda { 'Bar' }
p2.call # => "Bar"
You're passing a block to the method, as denoted by the & prefix and how you're calling it. That block is then converted into a Proc internally.
puts str.call inside your method would print the string, although why you'd want to define the method this way is another matter.
See Proc:
http://www.ruby-doc.org/core/classes/Proc.html
When the last argument of function/method is preceded by the & character, ruby expect a proc object. So that's why puts's output is what it is.
This blog has an article about the unary & operator.
I want to write a simple Ruby DSL to translate some statements and expressions into another language. A basic example would be:
some_function {
t + 2
}
Here, t is not a ruby variable and thus the block can't (and must not!) be evaluated by Ruby. So my best bet would be to use the parsing output (or AST) to do the translation myself. To do so, I can use ParseTree and ruby2ruby. However, I have other constructs that I would like to use, for example:
1.upto(10) {|x|
some_function {
t + x
}
}
Here, I have a local variable and I need to get its value in order to do my translation. However, in the function that does the block evaluation, I don't have access to the local variables of the calling block. If it were a global variable ($x), I could check if its name exists in the global_variables array and in the worst case use eval, but how could I do so for a local variable, if possible at all?
Update:
Just to clear up things. Like I said originally, I'm using ruby2ruby (and hence ParseTree) to get the AST (using to_sexp) corresponding to the block. But when using a local variable inside my block, I encounter the following:
[:dvar, :x]
And thus, I would need to get the value of a variable from its name as a string/symbol. And I can't use method_missing or instance_eval, because I want to translate the whole expression to another language or syntax (like a RPN).
Another solution not based on ParseTree would be welcome nonetheless, since it apparently is not fully supported with Ruby 1.9.
To get the variable values, use the proc's binding:
def some_function(&block)
b = block.binding
p [b.eval("t"), b.eval("x")]
end
t = 1
1.upto(10) {|x|
some_function {
t + x
}
}
Here, t is not a ruby variable and
thus the block can't (and must not!)
be evaluated by Ruby.
Any reason for the "not evaluated" restriction? It seems like method_missing would elegantly handle evaluating the "missing" t variable, but Ruby would automatically dereference the x variable.
You can use instance_eval against an object with t.
class Context
attr_accessor :t
def initialize(_t)
#t = _t
end
end
def some_function(&block)
puts Context.new(1).instance_eval(&block)
end
1.upto(10) {|x|
some_function {
t + x
}
}