I wrote a stack class to evaluate a postfix expression. I understand how to do it except for the order of it. Let's say I have a simple one like:
A B - C +
My only question is, would it be A - B, or B - A? I can't find any resource online that explains that part of evaluation.
Your operators are just functions. So you can define those functions however you want.
I personally would define - to take two arguments, and subtract the second from the first. This would be consistent with most people's expectations, and also how existing RPN calculators work. See, for instance, http://h41111.www4.hp.com/calculators/uk/en/articles/rpn.html for more on that.
Simple ES6 implementation:
const postfix = input => input.split(' ').reduce((result, token) =>
isNaN(token)
? [ eval(`${result.shift()}${token}${result.shift()}`), ...result ]
: [ token, ...result ]
, [])[0];
Related
Posting for two reasons: (1) I was stuck on unhelpful compiler errors for far too long for such a simple issue and I want the next person to google those messages to come upon my (or other) answers, and (2) I still don't understand disallowing a use clause, so my own answer is really incomplete.
In order to call a program in two places with mostly the same arguments, I want to use the '&' to append to a default list inline:
declare
Exit_Code : constant Integer := GNAT.OS_Lib.Spawn (Program_Name => "gprbuild", Args => (Default_GPR_Arguments & new String'(File_Name_Parameter)));
begin
if Exit_Code /= 0 then
raise Program_Error with "Exit code:" & Exit_Code'Image;
end if;
end;
However, the compiler complains that System.Strings.String_List needs a use clause:
operator for type "System.Strings.String_List" is not directly visible
use clause would make operation legal
But inserting use System.Strings.String_List yields:
"System.Strings.String_List" is not allowed in a use clause
I also got this warning:
warning: "System.Strings" is an internal GNAT unit
warning: use "GNAT.Strings" instead
So I substituted GNAT for System in the with and the use clause and got an extra error in addition to the original 'you need a use clause for System.Strings.String_List' one:
"GNAT.Strings.String_List" is not allowed in a use clause
Why is GNAT.Strings.String_List not allowed in a use clause? Section 8.5 on use clauses doesn't seem to state anything on disallowed packages, so is this a compiler bug? Is it possible to define a new package that cannot have a use clause?
In a use clause of the form
use Name;
Name must be a package name. GNAT.Strings.String_List is a subtype name, not a package name.
There are a number of ways to invoke "&" for String_List. The simplest is to use the full name:
GNAT.Strings."&" (Left, Right)
but presumably you want to be able to use it as an operator in infix notation, Left & Right. Ways to achieve this, in decreasing specificity:
function "&" (Left : GNAT.Strings.String_List; Right : GNAT.Strings.String_List) return GNAT.Strings.String_List renames GNAT.Strings."&"; This makes this specific function directly visible.
use type GNAT.Strings.String_List; This makes all primitive operators of the type directly visible.
use all type GNAT.Strings.String_List; This makes all primitive operations of the type (including non-operator operations) directly visible.
use GNAT.Strings; This makes everything in the package directly visible.
Looks like it is a design decision. And many other packages in System follows this rule. From the s-string.ads (package specification for System.String):
-- Note: this package is in the System hierarchy so that it can be directly
-- be used by other predefined packages. User access to this package is via
-- a renaming of this package in GNAT.String (file g-string.ads).
My guess why this is done in that way: because it isn't in the Ada specification, but extension from GNAT.
Generally speaking, Functional Programming prides itself for being clearer and concise. The fact that you don't have side-effects/state management makes it easier for developers to reason about their code and assure behaviours. How far does this truth reach?
I'm still learning Elixir but given the code from Coding Gnome:
def make_move(game = %{ game_state: state }, _guess)
when state in [:won, :lost] do
...
end
def make_move(game = %{ game_state: state }, _guess)
when state in [:pending] do
...
end
def make_move(game, guess) do
...
end
One could write it without any fanciness in Javascript as:
const makeMove = (game, guess) => {
switch(game.state) {
case 'won':
return makeMoveFinalState();
case 'lost':
return makeMoveFinalState();
case 'pending':
return makeMovePending();
}
}
Disregarding all the type/struct safety provided by Elixir compiler, an Elixir programmer would have to read the whole file before making sure that there wasn't a function with a different signature hijacking another, right? I feel that this increases the overhead while a programmer, because it's yet another thing you have to think about, even before looking at the implementation of the function.
Besides that, it feels to me as a misdirection because you can't be 100% sure that a case is ending up in that general make_move function unless you know beforehand all others and the signatures types, while with a conditional you have a clearer path of flow.
Could this be rewritten in a better way? At what point does these abstractions start to weight in the programmer?
I think this boils down mostly to preference and usually simple exercises with pattern matching with simple conditions do not show the range of "clarity" pattern matching can provide. But I'm suspect because I prefer pattern matching, any way, I'm gonna bite.
In this case, the switch could be said to be more readable and straightforward, but note that there's nothing preventing you from writing a very similar thing in Elixir (or erlang)
def make_move(game = %{ game_state: state }, _guess) do
case state do
state when state in [:won, :lost] -> # do things
:pending -> # do things
_else -> # do other things
end
end
Regarding the placement of different function clauses for the same function name, elixir will emit a warning if they're not grouped together, so that ends up just being your responsibility to write them together and in the correct order (it will also warn you if any of the branches is by definition unreachable, like placing a catch all before any specific branch that has matchings).
But I think that if for instance you add a slight change of the matching requirements for the pending state, then in my view it starts becoming clearer to write it in the erlang/elixir way. Say that when the state is pending there are two different execution paths, depending if it's your turn or something else.
Now you could write 2 specific branches for that with just function signatures:
def make_move(game = %{ game_state: :pending, your_turn: true }, _guess) do
# do stuff
end
def make_move(game = %{ game_state: :pending }, _guess) do
# do stuff
end
To do that in JS you would need to have either another switch, or another if. If you have more complex matching patterns then it easily becomes harder to follow, while on elixir I think the paths are quite clear.
If the other conditions could be more thornier, say when it's :pending and there's nothing on a stack key that holds a list, then again matching that becomes:
def make_move(game = %{ game_state: :pending, your_turn: true, stack: [] }, _guess) do
Or if there's another branch where it depends if the first item in the stack was something specific:
def make_move(game = %{ game_state: :pending, your_turn: true, player_id: your_id, stack: [%AnAlmostTypedStruct{player: your_id} | _] }, _guess) do
Here erlang/elixir would only match this if your_id was the same in both places where it's used in the pattern.
And also, you say "without fanciness" in JS, but different function heads/arity/pattern matching is nothing fancy in Elixir/Erlang, it's just like the language has support for switch/case based statements at a much lower level (at the module compilation level?).
I for one would love to have effective pattern matching & different function clauses (not destructuring only) in JS.
I am trying to replace all types in an AST.
Analyzing Java language using m3 model; definitions from here
If we take this code:
Int a = 1;
I am able to update the type of 1 to void for example.
But I am not able to change the type of the variable itself.
I've included some example lines.
Is someone able to point out the errors in the lines?
case \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions)
=> \method(\int(), "funcHolder", parameters, exceptions)
case \type(Type \type) => \void()
case \type => \void
Ok, excellent question. First your code and the errors it might have:
This looks good:
case \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions)
=> \method(\int(), "funcHolder", parameters, exceptions)
The definition is: data Declaration = \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions, Statement impl); (see here), and your code follows exactly the definition. Every abstract method declaration in the ASTs you've parsed will match with this, since there is another \method declaration for methods with bodies with an additional argument.
It may be that you do not have abstract method bodies in your example code, in that case this does nothing.
A simpler version would also work fine:
case \method(_, _, parameters, exceptions) => \method(\int(), "funcHolder", parameters, exceptions)
The next one has issues:
case \type(Type \type) => \void()
Because data Expression = \type(Type \type), that is an Expression and data Type = \void() that is a Type or data TypeSymbol = \void() it is a TypeSymbol the rewrite is not type-preserving and would do wrong things if the Rascal compiler would not detect this. Mostly it will probably not work for you because your example code does not contain this particular kind of expression. I suspect it might be the abstract notation for things such as int.class and Integer.class.
Then this one is "interesting":
case \type => \void()
In principle, if \type is not bound in the current scope, then this matches literally anything. But probably there is a function called \type or a variable or something somewhere, and thus this pattern tests for equality with that other thing in scope. Very nasty! It will not match with anything I would guess. BTW, we are planning a "Rascal Amendement Proposal" for a language change to avoid such accidental bindings of things in the scope of a pattern.
Later from the commments I learned that the goal was to replace all instances of a Type in the AST by void(), to help in clone detection modulo type names. This is done as follows:
case Type _ => \void()
We use a [TypedVariable] pattern, with the variable name _ to match any node of algebraic type Type and forget about the binding. That node will then be replaced by void().
My way of working in the absence of a content-assist tool for pattern matching is as follows:
find full one AST example of something you want to match, say Int a = 1;
copy it into the Rascal source file
remove the parts you want to abstract from by introducing variables or _
test on the original example
test on the rest of the system by printing out the loc that have matched and clicking on the locs to bring you to the code and see if it wasn't a false positive.
for example I want to rewrite Int to void, I find an example of Int in an AST and paste it:
visit (ast) {
case simpleType(simpleName("Int")) => Type::\void() // I added Type:: to be sure to disambiguate with TypeSymbol::void()
}
With some debugging code attached to print out all matches:
visit (ast) {
case e:simpleType(simpleName("Int")) => Type::\void()
when bprintln("found a type at <e.src?|unknown:///|>");
}
Maybe you find out that that has way too many matches, and you have to become more specific, so let's only change declarations Int _ = ....;, we first take an example:
\variables(simpleType(simpleName("Int")), [...lots of stuff here...])
and then we simplify it:
\variables(simpleType(simpleName("Int")), names)
and then include it in the visit:
visit (ast) {
case \variables(simpleType(simpleName("Int")), names) => \variables(Type::\void(), names)
}
Final remark, as you can see you can nest patterns as deeply as you want, so any combination is fine. A "complex" example:
\variables(/"Int", names)
This pattern finds any variable declaration where the name "Int" is used somewhere as part of the type declaration. That's more loose than our original and might catch more than you bargained for. It's just to show what combinations you might want to do.
A final example of this: find all variable declarations with a type name which starts with "Int" but could end with anything else, like "Integer" or "IntFractal", etc:
\variables(simpleType(simpleName(/^Int/)), names)
From their quickstart guide I got this following sample
alert cpu.is.too.high {
template = test
$metric = q("sum:rate{counter,,1}:os.cpu{host=your-system-here}", "1h", "")
$avgcpu = avg($metric)
crit = $avgcpu > 80
warn = $avgcpu > 60
}
I would guess it's a perlish DSL. What is the name of this language?
We just call it "Bosun's expression language" and is documented at http://bosun.org/expressions.html. As you said it is a custom DSL. It currently has the following qualities
It is not imperative. The language itself actually lacks true variables, the "$foo" are just text replacement
It is functional
It is well typed (functions accept and return specific types. Since the DSL is for alerting, we believe it is important to catch as many errors at possible at parse time.)
The guts implementation of the parser and lexer is based on that guts of text/template. A map function that takes an expression to operator on every X item in a series for an entire seriesSet is in the works, so the language is still a bit in the works. But I don't think we will be change the underlying design choices mentioned above (except maybe actually use real variables instead of text replacement at some point.)
I have code:
let join a ~with':b ~by:key =
let rec a' = link a ~to':b' ~by:key
and b' = link b ~to':a' ~by:(Key.opposite key) in
a'
and compilation result for it is:
Error: This kind of expression is not allowed as right-hand side of
`let rec' build complete
I can rewrite it to:
let join a ~with':b ~by:key =
let rec a'() = link a ~to':(b'()) ~by:key
and b'() = link b ~to':(a'()) ~by:(Key.opposite key) in
a'()
It is compilable variant, but implemented function is infinitely recursive and it is not what I need.
My questions: Why is first implementation invalid? How to call two functions and use their results as arguments for each other?
My compiler version = 4.01.0
The answer to your first question is given in Section 7.3 of the OCaml manual. Here's what it says:
Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.
Your names appear as function arguments, which isn't supported.
I suspect the reason is that you can't assign a semantics otherwise. It seems to me the infinite computation that you see is impossible to avoid in general.