Adding to a parameter in a method call, outside of parameter parentheses? - ruby

I saw this line of code in a test I'm trying to get to pass.
stack = Overflow.at(10) + 3
I've never seen a method called like this. Every book/blog I've seen only shows what's happening inside the parentheses (like the splat operator, multiple params, etc). I've never seen something added to a method call, outside the parentheses, and I can't even figure out how to word what's happening to look it up to research/learn.
Any help on what exactly is happening, even if it's just what exactly this is technique is called for me to research, is greatly appreciated.

If Overflow.at(10) returns int you may treat
stack = Overflow.at(10) + 3
as shorten version of:
overflow = Overflow.at(10)
stack = overflow + 3
It's more compact, but the result is the same.

Related

Implementing comparison operators in Bytecode using ASM

I'm working on a personal project of mine creating a simple language which is compiled to Java Bytecode. I'm using the ASM library version 7.3.1 but I've hit a problem with Frames that I can't quite figure out.
This is actually two questions rolled into one. I'm trying to implement simple comparison operators e.g. >, <, >= etc. These operators should return a boolean result obviously. I can't see a way of implementing this directly in Bytecode so I'm using using FCMPG to compare two floats that are already on the stack and then using IFxx to push either a 1 or 0 to the stack depending on which operator I'm generating code for.
For example here is my code for >:
val label = new Label()
mv.visitInsn(FCMPG) // mv is my MethodVisitor, there are 2 Floats on the stack
mv.visitJumpInsn(IFGT, label)
mv.visitInsn(ICONST_1)
mv.visitLabel(label)
mv.visitInsn(ICONST_0)
Question 1: Is this the correct approach for implementing comparison operators or am I missing a simpler method?
Question 2: Running this code generates this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at org.objectweb.asm.Frame.merge(Frame.java:1268)
at org.objectweb.asm.Frame.merge(Frame.java:1244)
at org.objectweb.asm.MethodWriter.computeAllFrames(MethodWriter.java:1610)
at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1546)
at compiler.codegen.default$$anon$1.generateConstructor(default.scala:138)
at compiler.codegen.default$$anon$1.generateCode(default.scala:157)
at compiler.codegen.default$$anon$1.generateCode(default.scala:21)
at compiler.codegen.package$.generateCode(package.scala:21)
at compiler.codegen.package$CodeGeneratorOp.generateCode(package.scala:17)
at Main$.main(main.scala:27)
at Main.main(main.scala)
I know this is to do with Frames but I don't really understand frames enough to know what I'm doing wrong. I've tried adding mv.visitFrame(F_SAME, 0, null, 0, null) after visitLabel but I get the same error.
1) Yes, this is the correct way to do it. I believe the actual Java compiler does something very similar.
2) You get a verification error because you forgot to add a jump to the end of the if block. If you look closely at your code, you'll see that when the jump isn't taken both branches are executed and you end up with both 0 and 1 on the stack, which leads to a verification error. You need to insect a second jump so only the constant you wish gets pushed to the stack in this case. It should be something like this:
val then_label = new Label()
val end_label = new Label()
mv.visitInsn(FCMPG) // mv is my MethodVisitor, there are 2 Floats on the stack
mv.visitJumpInsn(IFGT, then_label)
mv.visitInsn(ICONST_1)
mv.visitGoto(end_label)
mv.visitLabel(then_label)
mv.visitInsn(ICONST_0)
mv.visitLabel(end_label)

Why am I not getting a match?

I have a list structure called "stack".
At the point in my program which is causing problems, this is what stack holds:
stack([[s]],[np,[noun,john]])
I got this from running a trace, and its what stack is supposed to be holding.
When writing the next rule which is supposed to match this.
if
buffer([[Word|_]])
and aux(Word)
and stack([s],[np,[noun, john]])
If I do this then the rule executes as its supposed to. But I need to use a variable here instead of using "and stack([[s]],[np,[noun,john]])". However when I try to use anything else, the rule does not fire. I can't work out why. Other rules work fine when I use variables in the list.
Ive tried
stack([s]|Foo)
stack([s]|[Foo])
stack([MyHead]|[MyTail]... and literally every other combination I can think of.
I'm not entirely sure what is causing this problem
Your stack seems to have arity 2, where each arg is a list.
These aren't valid syntax for lists
stack([s]|Foo)
stack([s]|[Foo])
...
but since some Prolog declare the (|)/2 operator as alternative to (;)/2 (i.e. disjunction), you will not see any syntax error.
To understand you problem, you could try to unify, by mean of unification operator (=)/2
?- stack(S, Foo) = stack([[s]],[np,[noun,john]]).
you will get
S = [[s]]
Foo = [np,[noun,john]]

Perform operations within string format

I am sure that this has been asked, but I can't find it through my rudimentary searches.
Is it discouraged to perform operations within string initializations?
> increment = 4
=> 4
> "Incremented from #{increment} to #{increment += 1}"
=> "Incremented from 4 to 5"
I sure wouldn't, because that's not where you look for things-that-change-things when reading code.
It obfuscates intent, it obscures meaning.
Compare:
url = "#{BASE_URL}/#{++request_sequence}"
with:
request_sequence += 1
url = "#{BASE_URL}/#{request_sequence}"
If you're looking to see where the sequence number is coming from, which is more obvious?
I can almost live with the first version, but I'd be likely to opt for the latter. I might also do this instead:
url = build_url(++request_sequence)
In your particular case, it might be okay, but the problem is that the position where the operation on the variable should happen must be the last instance of the same variable in the string, and you cannot always be sure about that. For example, suppose (for some stylistic reason), you want to write
"Incremented to #{...} from #{...}"
Then, all of a sudden, you cannot do what you did. So doing operation during interpolation is highly dependent on the particular phrasing in the string, and that decreases maintainability of the code.

Why do we call functions as arguments in other functions? [duplicate]

This question already has answers here:
Should a function have only one return statement?
(50 answers)
Is good to call function in other function parameter?
(3 answers)
Closed 9 years ago.
I've got a style question. It's something I've been doing since forever, but I can't figure out why, exactly.
In most languages I've used, you can call a method that returns a value as an argument to another method:
foo(bar())
which is equal to
var bar=bar()
foo(bar)
For some reason, the latter seems unsavory. Why is that? Is the first more readable, efficient, or clean?
It's not necessarily equal.
foo(bar());
means "call bar and pipe its arguments to foo"
var retBar = bar();
foo(retBar);
means "initalize retBar, then call bar, store whatever it returns to retBar, and then call foo with retBar as its argumnet."
Depending on how expensive variables are to declare, the latter may have a larger memory footprint or slower runtime.
Really, though, it's an entire extra statement -- two extra statements, actually, depending on language -- and it leaves your code less clean. The only time I do method #2 is when I have some reason to use bar()'s value, even if only to peek at it in a debugger.
I feel its a blend of all what you said. The former construct is favorable since
a. It prevent the declaration of an additional variable to achieve the same result.
b. Its more cleaner since its more easier to read/ understand
var accountBalance = sum ( principalAmount + calculateInterest() )
than
var varCalculateInterest = calculateInterest();
var accountBalance = sum ( principalAmount + calculateInterest() )
c. If you use features like recursion, you obviously will try the former. You will need a lot of temp variables to store the intermediate results. Please see an example below.
return concatenate(quicksort(less), pivot', quicksort(greater))

What is the purpose of "!" and "?" at the end of method names?

Sometimes I see methods in Ruby that have "?" and "!" at the end of them, e.g:
name = "sample_string"
name.reverse
name.reverse!
name.is_binary_data?
I was wondering what their purpose is? Are they just syntax sugarcoating?
It's "just sugarcoating" for readability, but they do have common meanings:
Methods ending in ! perform some permanent or potentially dangerous change; for example:
Enumerable#sort returns a sorted version of the object while Enumerable#sort! sorts it in place.
In Rails, ActiveRecord::Base#save returns false if saving failed, while ActiveRecord::Base#save! raises an exception.
Kernel::exit causes a script to exit, while Kernel::exit! does so immediately, bypassing any exit handlers.
Methods ending in ? return a boolean, which makes the code flow even more intuitively like a sentence — if number.zero? reads like "if the number is zero", but if number.zero just looks weird.
In your example, name.reverse evaluates to a reversed string, but only after the name.reverse! line does the name variable actually contain the reversed name. name.is_binary_data? looks like "is name binary data?".
Question mark indicates that the method returns boolean. Already answered here:
What does the question mark operator mean in Ruby?
The bang indicates that the method acts on the object itself. Already answered here:
Why are exclamation marks used in Ruby methods?
In Ruby the ? means that the method is going to return a boolean and the ! modifies the object it was called on. They are there to improve readability when looking at the code.
In contrast to the – I suppose – majority of programming languages ...
Ruby, methods are allowed to end with question marks or exclamation marks.
By convention, methods that answer questions (i.e. Array#empty? returns true if the receiver is empty) end in question marks.
Potentially “dangerous” methods (ie methods that modify self or the arguments, exit! etc.) by convention end with exclamation marks.
From: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/, Section Funny method names
Beware, this isn't always the case. Take for example, Ruby Array#concat http://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat.
Where you can get burnt badly is something like MyActiveRecordModel.column_names.concat([url]). Later calls related to MyActiveRecordModel will try to look for a column of 'url' for MyActiveRecordModel and throw.
Instead you must clone it before doing the concat. Fortunately my test suite caught this one, but.. heads up!

Resources