I have an XQuery library module including some functions that take no arguments.
I'm considering rewriting these functions as variables, to make it a little quicker to access them.
However, the content of some of them are computationally expensive expressions. As functions, they will obviously be evaluated only when called. But as variables, I'm unsure whether they will automatically be evaluated when the library module is imported.
Only some queries that import this module would use those variables, and justify their evaluation. For others that don't use the variables, said evaluation would be an unnecessary overhead.
There would be no problem, however, if imported variables are lazily evaluated: I could import the library module on any query, knowing that these expensive variables are evaluated only if actually used by the main module.
I know that this is just a matter of writing prefix:myImportedFunction() vs. $prefix:myImportedVariable, but it's an uncertainty that I'd like to dispel.
I believe this behavior is implementation dependent. I'm specially interested in the behavior in BaseX and Saxon-HE. Do they lazily evaluate imported variables?
Saxon will normally use lazy evaluation for global variables. The exception is if run-time tracing is enabled (which may be done if you are debugging in an IDE); it then switches to eager evaluation to make debugging more tractable.
In BaseX, only those variables will be optimized (and, thus, possibly pre-evaluated) if they are referenced in the executed code. For example, in the following expression, $v will not be evaluated:
declare variable $expensive := (1 to 100000000)[. = 1];
123
The pre-evaluation of accessed variables was chosen because it enables many subsequent optimizations in BaseX. However, lazy evaluation of variables can be enforced by adding the Q{http://basex.org}lazy annotation:
declare namespace basex = 'http://basex.org';
declare %basex:lazy variable $expensive := (1 to 100000000)[. = 1];
(1, $expensive)[1]
Related
Let's say I'm invoking something like this
Enum.count(list)
And list is not defined in 'upper scope'. In most of languages you'll probably get something like Variable list is undefined, but in Elixir (it comes from Erlang, so I hope it's same behaviour) you'll be getting undefined function list/0 (there is no such import).
What's the difference in Elixir from other (let's say imperative) programming languages in sense of distinction between variable and function?
Also I've noticed you can make a function in module, and if it takes zero arguments, you can call it without parentheses, I was wondering what's special about that. (was answered below by #sabiwara)
Elixir used to consider parentheses optional for all function calls, including 0-arity functions like Kernel.node/0:
iex> node
:nonode#nohost
This behavior has since been deprecated and will emit a compile time warning:
warning: variable "node" does not exist and is being expanded to "node()", please use parentheses to remove the ambiguity or change the variable name
Parentheses for non-qualified calls are optional, except for zero-arity calls, which would then be ambiguous with variables.
But since it would be a breaking change to just change this behavior, it still works and gets interpreted, in your case, as list().
This might change in Elixir 2.0. A discussion on this topic here.
In most languages with switch statements, switch is a special form designed such that the possibilities are evaluated lazily and the compiler knows how to optimise the selection of statements based on the given input. R, mostly already being lazy, does not need some of this. However, R's switch statement is still a function call, rather than any sort of special form. Does this mean that R's switch statement is slower than it would be if it were a special form? Or does R's interpreter know to optimise it as if it were a special form?
If you look at internal code of switch in file src/main/builtin.c, you can read in lines 1009-1025 :
This is a SPECIALSXP, so arguments need to be evaluated as needed.
SPECIALSXP means :
no SEXPTYPE Description
7 SPECIALSXP special functions
So switch is actually a special function which passes unevaluated arguments to the internal function.
Further reading the source code from line 1030 to line 1104 shows that as explained in ?switch, the function either handles character or number in a simple and not fully optimized way.
This probably explains why switch isn't particularly fast in situations which would for example require a binary search.
I'm currently programming on Julia via command line session.
I know that the predefined functions in Julia (e.g. sqrt) can take on a variable value but in a particular session I tried to use the function as sqrt(25) and it gave me 5.0 but in the same session when I wrote sqrt=9, then it says
"Error: cannot assign variable Base.sqrt from module Main"
and if I have to make this happen I have to open a new session all over again and assign a variable value to sqrt sqrt=9and when I do so then again it says
ERROR:MethodError: objects of type Int64 are not callable
when I try to use sqrt as a function.
The same thing happens with pi.
The topic you are asking about is a bit tricky. Although I agree with the general recommendation of PilouPili it is sometimes not that obvious.
Your question can be decomposed into two issues:
ERROR:MethodError: objects of type Int64 are not callable
This one is pretty clear, I guess, and should be expected if you have some experience in other programming languages. The situation is that name sqrt in the current scope is bound to value 9 and objects of type Int64 are not callable.
The other error
"Error: cannot assign variable Base.sqrt from module Main"
is more complex and may be non obvious. You are free to use name sqrt for your own variables in your current scope until you call or reference the sqrt function. Only after such operations the binding to sqrt is resolved in the current scope (only recently some corner case bugs related to when bindings are resolved were fixed https://github.com/JuliaLang/julia/issues/30234). From this moment you are not allowed to change the value of sqrt because Julia disallows assigning values to variables imported from other modules.
The relevant passages from the Julia manual are (https://docs.julialang.org/en/latest/manual/modules/):
The statement using Lib means that a module called Lib will be available for resolving names as needed. When a global variable is encountered that has no definition in the current module, the system will search for it among variables exported by Lib and import it if it is found there. This means that all uses of that global within the current module will resolve to the definition of that variable in Lib.
and
Once a variable is made visible via using or import, a module may not create its own variable with the same name. Imported variables are read-only; assigning to a global variable always affects a variable owned by the current module, or else raises an error.
To better understand what these rules mean I think it is best to illustrate them with an example:
julia> module A
export x, y
x = 10
y = 100
end
Main.A
julia> using .A
julia> x = 1000
1000
julia> y
100
julia> y = 1000
ERROR: cannot assign variable A.y from module Main
on the other hand by calling import explicitly instead of using you resolve the binding immediately:
julia> module A
export x, y
x = 10
y = 100
end
Main.A
julia> import .A: x, y
julia> x = 1000
ERROR: cannot assign variable A.x from module Main
And you can see that it is not something specific to Base or functions but any module and any variable. And this is actually the case when you might encounter this problem in practice, as it is rather obvious that sqrt is a predefined function, but something like SOME_CONSTANT might or might not be defined and exported by the modules you call using on and the behavior of Julia code will differ in cases when you first assign to SOME_CONSTANT in global scope and when you first read SOME_CONSTANT.
Finally, there is a special case when you want to add methods to functions defined in the other module - which is allowed or not depending on how you introduce the name in the current scope, you can read about the details here what are the rules in this case.
Bogumił's answer is good and accurate, but I think it can be described a bit more succinctly.
Julia — like most programming languages — allows you to define your own variables with the same name as things that are built-in (or more generally, provided by using a package). This is a great thing, because otherwise you'd have to tip-toe around the many hundreds of names that Julia and its packages provide.
There are two catches, though:
Once you've used a built-in name or a name from any package, you can no longer define your own variables with the same name (in the same scope). That's the Error: cannot assign variable Base.sqrt from module Main: you've already used sqrt(4) and now are trying to define sqrt=2. The workaround? Just use a different name for your variable.
You can define your own variable with the same name as a built-in name or a name from any package if you've not used it yet, but then it takes on the definition you've given it. That's what's happening with ERROR: MethodError: objects of type Int64 are not callable: you've defined something like sqrt=2 and then tried to use sqrt(4). The workaround? You can still reference the other definition by qualifying it with its module name. In this case sqrt is provided by Base, so you can still call Base.sqrt. You can even re-assign sqrt = Base.sqrt to restore its original definition.
In this manner, the names provided by Base and other packages you're using are a bit like Schrödinger's cat: they're in this kinda-there-but-not-really state until you do something with them. If you look at them first, then they exist, but if you define your own variable first, then they don't.
I've got a symbol that represents the name of a function to be called:
julia> func_sym = :tanh
I can use that symbol to get the tanh function and call it using:
julia> eval(func_sym)(2)
0.9640275800758169
But I'd rather avoid the 'eval' there as it will be called many times and it's expensive (and func_sym can have several different values depending on context).
IIRC in Ruby you can say something like:
obj.send(func_sym, args)
Is there something similar in Julia?
EDIT: some more details on why I have functions represented by symbols:
I have a type (from a neural network) that includes the activation function, originally I included it as a funcion:
type NeuralLayer
weights::Matrix{Float32}
biases::Vector{Float32}
a_func::Function
end
However, I needed to serialize these things to files using JLD, but it's not possible to serialize a Function, so I went with a symbol:
type NeuralLayer
weights::Matrix{Float32}
biases::Vector{Float32}
a_func::Symbol
end
And currently I use the eval approach above to call the activation function. There are collections of NeuralLayers and each can have it's own activation function.
#Isaiah's answer is spot-on; perhaps even more-so after the edit to the original question. To elaborate and make this more specific to your case: I'd change your NeuralLayer type to be parametric:
type NeuralLayer{func_type}
weights::Matrix{Float32}
biases::Vector{Float32}
end
Since func_type doesn't appear in the types of the fields, the constructor will require you to explicitly specify it: layer = NeuralLayer{:excitatory}(w, b). One restriction here is that you cannot modify a type parameter.
Now, func_type could be a symbol (like you're doing now) or it could be a more functionally relevant parameter (or parameters) that tunes your activation function. Then you define your activation functions like this:
# If you define your NeuralLayer with just one parameter:
activation(layer::NeuralLayer{:inhibitory}) = …
activation(layer::NeuralLayer{:excitatory}) = …
# Or if you want to use several physiological parameters instead:
activation{g_K,g_Na,g_l}(layer::NeuralLayer{g_K,g_Na,g_l} = f(g_K, g_Na, g_l)
The key point is that functions and behavior are external to the data. Use type definitions and abstract type hierarchies to define behavior, as is coded in the external functions… but only store data itself in the types. This is dramatically different from Python or other strongly object-oriented paradigms, and it takes some getting used to.
But I'd rather avoid the 'eval' there as it will be called many times and it's expensive (and func_sym can have several different values depending on context).
This sort of dynamic dispatch is possible in Julia, but not recommended. Changing the value of 'func_sym' based on context defeats type inference as well as method specialization and inlining. Instead, the recommended approach is to use multiple dispatch, as detailed in the Methods section of the manual.
I'm building on some old Common Lisp code written by others, which includes lines such as the following at the start of a few functions:
(declare (ftype (function (&rest float) float) + - * min max))
My understanding is that the purpose of this is to tell the compiler that the five functions listed at the end of the form will only be passed floats. The compiler may use this information to create more efficient code.
Some Lisps do not complain about this declaration (ABCL, CCL, ECL, LispWorks, CLISP), but SBCL will not accept this declaration in the default configuration. SBCL can be made to accept it by placing
(unlock-package 'common-lisp)
in the .sbclrc initialization file. That's what I've been doing for the last year or so. I assume that this is needed because +, -, etc. are in that package, and the code alters these functions' declarations.
My question is: Can declaring the function type of built-in functions such as + and min have a beneficial effect on compiled code in SBCL? (If it can, then why does SBCL complain about these declarations by default?) Would I be better off removing such ftype declarations, and then getting rid of the unlock-package line in .sbclrc?
Thanks.
My understanding is that the purpose of this is to tell the compiler that the five functions listed at the end of the form will only be passed floats. The compiler may use this information to create more efficient code.
Also, they will only return floats. With certain optimization settings, the a Common Lisp compiler does not generate runtime checks and may only generate code for float computations. Also SBCL may show compile-time warnings in certain cases, where it detects that code violates type declarations.
It's also a source for errors, since from now on (within the scope of the declaration) basic functions like +and - are declared not to work on other number types (integer, complex, ...).
So, what is the purpose for these declarations? Since it is portable code (and most implementations don't implement compile-time type checking), it can only be for optimization purposes. Some of that might not be necessary in SBCL, since it uses type inference.
Why does SBCL not allow to alter the built-in functionality by default? It is so to prevent shooting in your foot: you are altering the base language. Now basic numeric operations may lead to errors.
Ways to deal with that:
use only local declarations, don't alter the language globally. You indicate that these are only locally declared - that's good.
declare the values of variables instead
write special functions for the float case and declare them inline.
only unlock the package CL during compilation of these few functions. keep it locked later.
My question is: Can declaring the function type of built-in functions such as + and min have a beneficial effect on compiled code in SBCL?
You can check that by looking at the disassembled code and also by profiling. Make sure that you compile the function with the right optimization setting. In Common Lisp the function DISASSEMBLE should show you machine code in a readable way. The SBCL compiler should also tell you if it can't optimize the compiled code.