I'd like to understand how directives in Spray work. As per the documentation:
The general anatomy of a directive is as follows:
name(arguments) { extractions =>
... // inner Route
}
My basic understanding is that in the below snippet, 32 is passed as a parameter to method test.
test {
32
}
However, in the above directive name example, it is said arguments are passed into inner route, which is an anonymous function.
Could someone please help me understand the syntax and the flow starting from how the arguments are extracted and passed into an inner route?
You're right that that syntax passes 32 to the function test. What you're missing is that a Directive accepts a function as an argument (remember, we're doing functional programming now so functions are values). If you wanted to write this:
path(IntNumber) {
userId =>
complete(s"Hello user $userId")
}
in a less DSL-ey fashion, you could do this:
val innerFunction: Int => Route = {userId => complete(s"Hello user $userId")}
(path(IntNumber))(innerFunction)
or even this:
def innerMethod(userId: Int): Route = complete(s"Hello user $userId")
(path(IntNumber))(innerMethod)
The mechanics of how this is actually accomplished are... complex; this method makes a Directive implicitly convertible to a function:
implicit def pimpApply[L <: HList](directive: Directive[L])(implicit hac: ApplyConverter[L]): hac.In ⇒ Route = f ⇒ directive.happly(hac(f))
This is using the "magnet pattern" to select an appropriate hac, so that it can take a function in the inner path (with an appropriate number of arguments) if the directive extracts parameters, or a value in the inner path (a plain route) if the directive doesn't extract parameters. The code looks more complicated than it is because scala doesn't have direct support for full dependent typing, so we have to emulate it via implicits. See ApplyConverterInstances for the horrible code this necessitates :/.
The actual extracting all happens when we get an actual route, in the happly method of the specific directive. (If everything used HList everywhere, we could mostly avoid/ignore the preceding horrors). Most extract-ey directives (e.g. path) eventually call hextract:
def hextract[L <: HList](f: RequestContext ⇒ L): Directive[L] = new Directive[L] {
def happly(inner: L ⇒ Route) = ctx ⇒ inner(f(ctx))(ctx)
}
Remember a Route is really just a RequestContext => Unit, so this returns a Route that, when passed a RequestContext:
Runs f on it, to extract the things that need extracting (e.g. URL path components)
Runs inner on that; inner is a function from e.g. path components to the inner route.
Runs that inner route, on the context.
(The following was edited in by a mod from a comment conversation):
Fundamentally it's pretty elegant, and it's great that you can see all the spray code and it's ordinary scala code (I really recommend reading the source when you're confused). But the "bridging" part with the ApplyConverter is complex, and there's really no way around that; it comes of trying to do full dependent types in a language that wasn't really designed for them.
You've got to remember that the spray routing DSL is a DSL; it's the kind of thing that you'd have to have as an external config file in almost any other language. I can't think of a single web framework that offers the same flexibility in routing definitions that spray does with complete compile-time type safety. So yes, some of the things spray does are complex - but as the quote goes, easy things should be easy and hard things should be possible. All the scala-level things are simple; spray is complex, but it would be even more complex (unusably so) in another language.
Related
I am trying to learn a bit about Vala and wanted to create a Calculator to test how Gtk worked. The problem is that I coded everything around the supposition that there would be a way to parse a string that contained the required operations. Something like this:
string operation = "5+2/3*4"
I have done this with Python and it is as simple as using the compilers parser. I understand Python is math oriented, but I thought that perhaps there would be Vala library waiting for me as an answer... I haven't found it if it does exist, but as I was looking at the string documentation, I noticed this part:
/* Strings prefixed with '#' are string templates. They can evaluate
* embedded variables and expressions prefixed with '$'.
* Since Vala 0.7.8.
*/
string name = "Dave";
println (#"Good morning, $name!");
println (#"4 + 3 = $(4 + 3)");
So... I thought that maybe there was a way to make it work that way, maybe something like this:
stdout.printf(#"$(operation)")
I understand that this is not an accurate supposition as it will just substitute the variable and require a further step to actually evaluate it.
Right now the two main doubts I am having are: a) Is there a library function capable of doing this? and b) Is it possible to work out a solution using string templates?
Here's something I found that would do the work. I used the C++ libmatheval library, for this I first required a vapi file to bind it to Vala. Which I found here. There are a lot of available vapi files under the project named vala-extra-apis, and they are recognized in GNOME's Vala List of Bindings although they are not included at install.
You could parse the expression using libvala (which is part of the compiler).
The compiler creates a CodeContext and runs the Vala parser over a (or several) .vala file(s).
You could then create your own CodeVisitor decendant class that visits the necessary nodes of the parse tree and evaluates expressions.
As far as I can see there is no expression evaluator that does this, yet. That is because normally vala code is translated to C code and the C compiler then does compile time expression evaluation or the finished executable does the run time evaluation.
Python is different, because it is primarily a scripting language and has evaluation build directly into the runtime / interpreter.
I need to parse something during the runtime of my eclipse plugin (created with Xtext) which would then be treated as if the user has typed it in but without actually popping up and beeing visible for the user as an input of himself.
For exmample I have this input:
for "i" from 1 to 3 do {};
My problem woth this input is that the variable i is not declared as a normal declaration with a "=" but I need the parser to tell that it is one. So I want to let the parser parse
i = 1;
so it recognizes it as a normal declaration and allows cross-references to it.
Greeting Krzmbrzl
EDIT:
All in all the thing I want is to add a statement i=1; to the AST
I just want to have eclipse support for an existing language so I'm not writing an interpreter nor a generator. The problem is that when I have a for-loop like above the actual interpreter of that language declares a variable i (or however it's named in the loop header) and therefore this variable is available in the loop body. In my case my parser doesn't recognise i as a variable because it only knows that a declaration is done via "=" so I can't use i in the loop body (if I try so I get the error that the declaration i cannot be resolved). This is why I want to add this declaration manually when such a loop is created. I don't need to worry about any compiling or interpreting difficulties because I don't do this myself. As I already said I just want to have all the cool eclipse features for this language.
Ok, now I understand your problem. It is still no good idea to add any element to the AST to resolve any cross reference! You don't do that! Instead you should try to refactor your grammar in a way that "i" in for "i" from ... is a compatible declaration of a variable. There are several tricks to do that. Have you completely read the Xtext documentation? Have also read the Xtext book? Both documents tell a lot about how to make Xtext do things you will not expect.
Anyway, two tricks I often use are:
Introduce an unused, abstract Parser Rule which you can then use as destination of a cross reference, but which is never used as an attribute (containment reference).
AbstractDecl:
VarDecl | ForVarDecl;
VarDecl:
name=ID ...;
ForVarDecl:
'"' name=ID '"';
For:
'for' decl=ForVarDecl 'from' from=INT 'to' to=INT 'do' block=Block;
...
StatementWithCR:
ref=[AbstractDecl] ...;
Define any ParserRule, which returns an other type.
ForDecl returns VarDecl:
'"' name=ID '"';
If you would post the grammar which corresponds to this specific problem, we could develop a solution which is safe. Adding anything to the AST during live processing content of the editor will lead to a faulty state which can destroy your document.
I find Erlang's module arity import /n where n is the number of arguments rather bizarre.
In Java and various other languages you can do something like:
import static com.stuff.Blah.myFunction;
Which will import all overloaded Blay.myFunction(..) regardless of parameters.
Besides I guess being explicit why did the language designers decide this was a good idea (I'm not trying to criticize the language... just curious)?
Does it have to do with code swapping?
Or does it have to do with hiding guard methods for recursion? If so why not allow arity on export but no need for arity on import?
Why would I want to be that explicit? That is import the two argument function but not the the three argument of myFunction?
You should be aware of what importing functions in Erlang really does. It is a pure textual transformation. If I do an -import(foo, [bar/1,baz/2]). it means that when I write a call like bar(5) or baz(a, 3) the compiler transforms these to foo:bar(5) and foo:baz(a, 3). That is all it does, nothing else. It doesn't check anything:
It doesn't check if the module foo contains the functions bar/1 or baz/2.
It doesn't even check if the module foo exists.
Really all it does is hide that you are calling a function in another module. That is why the recommendation from experienced Erlangers is "don't use it". It was a mistake. Unfortunately it is much easier to add stupid things than to get rid of them so we were never able to remove it.
"Does it have to do with code swapping?"
Yes, sort of. The unit of all code handling in Erlang is the module. So you compile modules, load modules, purge and delete modules. This means that there are no inter-module dependencies at all in the system and the compiler makes no assumptions about other modules when it is compiling a module. No assumptions are made that the environment in which a module is compiled will be the same in which it is run. That is why it is at runtime the system checks whether the function you are trying to call in another exists, or even if the module itself exists. That is why the import was a purely textual transformation.
Erlang was originally developed in Prolog.
In Prolog, the arity adds additional meaning to what you consider to be the 'arguments, as I understand from a function' in a procedural programming language. But that model does not apply here.
The so-called clauses 'married(X,Y).' and 'married(X,Y,Z).' imply a different kind of relationship 'married', which can be declared as married/2 and married/3.
In procedural programming, 'add(a,b)' or 'add(a,b,c)' are intended to generate the addition of a different number of arguments. That's not immediately the case in Prolog, where it is possible to have the relationship 'a and b, added' or 'a, b and c, added' mean something else. Needless to say, Prolog allows you to declare 'add' as you would expect a function would do. But it allows for more. More available meaning, means more need to control it.
And as in any module system, selecting what you want to expose to external clients makes sense: hence the declaration of arity.
Does it have to do with code swapping?
Kind of. The modules in Erlang are compiled separately (which is part of what allows code swapping), unlike Java classes, so the compiler doesn't know how many versions of the imported function with different arities exist. It could assume that all calls of a function with the given name come from the same module, of course, but the designers likely decided it wasn't particularly useful.
In fact, you rarely want to use imports at all, at least in my experience, just as you rarely use static imports in Java. Just write module:function, like Class.staticMethod.
Or does it have to do with hiding guard methods for recursion?
No, since not importing functions doesn't hide them in any way.
I've read on the Lua wiki / here / etc. on how to sandbox lua code generally. But I haven't been able to find something that disallows function creation. For example, the example here provides a sample code as:
assert(run [[function f(x) return x^2 end; t={2}; t[1]=f(t[1])]])
And that's with an empty environment. But I want to eliminate the ability to create a function (the 1st part of the code) - e.g., just allow expressions. Any idea on how to do that? Does it have to be in C somehow? Thanks in advance!
If you want to evaluate expressions only, you could try this:
function run(s) return loadstring("return "..s)() end
(error handling omitted)
This simple solution will prevent most `attacks', but not eliminate them because one can say
(function () f=function(x) print"hello" end end)()
which defines a new function named f.
Your best bet is to use a sandbox and not worry about what the user does to the environment, because it'll not be your environment.
You can try detecting the creation of functions by looking for the string "function" before allowing the execution of the lua script. For example from your C/C++ backend.
If "function" appears throw a "you are not allowed to create functions" error and don't execute the code.
A couple notes:
You might want to try to customize the detection a bit more - only throw errors if you detect function followed by blanks and an opening parenthesis, for example. I'm leaving that as an exercise.
You should be aware that there are some standard lua functions that kindof expect the users to be able to create functions - for example, the string table has several of those. Without creating functions, it'll be very difficult for your users to work with strings (it is already difficult enough with functions...)
Pursuant to this question:
Redefining Commands in a New Environment
How does one redefine (or define using \def) a macro that uses parameters? I keep getting an illegal parameter definition in \foo error. Since I require custom delimiters, I can't use \newcommand or \renewcommand.
A general form of my code looks like this:
\newenvironment{foo}{%
...spacing stuff and counter defs...
\def\fooitem#1. #2\endfooitem{%
...stuff...
}
\def\endfooitem{endfoo}
}
{...after material (spacing)...}
This must be possible. Right now I'm using plain-TeX definitions (as I mentioned in the question above) but I'd really like to be consistent with the LaTeX system.
You need to double the # characters for every nested definition. Internally, a \newcommand or a \newenvironment is calling \def.
\newenvironment{foo}{%
...
\def\fooitem##1. ##2\endfooitem{%
...
Besides that, this is the way to do what you're trying to do; there is no pure-LaTeX method to define a macro with delimited arguments.