I've seen a variable scope propagation to the inner function in previous versions of k. See eval: {[t;c]{x*t+y}/c} in http://www.math.bas.bg/bantchev/place/k.html
But if I try to do the same in modern k, I get an error:
KDB+ 3.6 2018.05.17 Copyright (C) 1993-2018 Kx Systems
q)\
{[k]{x*x}k}3
9
{[k]{x*x+k}k}3
'k
[2] k){x*x+k}
^
)
So why this error happens? Is such variable scope propagation 'banned' in modern q?
Indeed, k4, the most recent implementation of k by kx does not support closures. In fact, the article you refer to does mention that in a section called "Changes to the Language":
K4/q is a change over K3 in a number of significant ways, such as:
...
Nested functions in K4 and q cannot refer to surrounding function's local
variables. (Often, the lack of this ability can be circumvented by
making use of function projection.)
It turns out the lack of support of lexical scoping has not always been the case. Although the only officially documented language nowadays is q, one can still find a reference manual for k2, an implementation of k circa 1998, for example here: http://www.nsl.com/k/k2/k295/kreflite.pdf. Section "Local functions" on page 158 reads:
Local Functions
Suppose that the function g is defined within the body of another
function f and uses the variable x in its definition, where x is local
to f. Then x is a constant in g, not a variable, and its value is the
current one when g is defined. For example, if:
f:{b:3; g:{b}; b:4; g[]}
The value of f is the value of the local function g, which turns out to be 3, the value of b when g is defined,
not the subsequent value 4.
f[]
3
(I highly recommend reading the whole document, by the way).
I don't know why the support of closures was dropped but I think it was because of performance reasons, especially during interprocess communications.
Related
After this
restart; about(x); assume(x>0); f:=3*x; x:='x': about(x);
Originally x, renamed x~:
is assumed to be: RealRange(Open(0),infinity)
f := 3*x~
x:
nothing known about this object
I can use indets to access the variable x (looks like it's still x~ in f), for example
eval(f,indets(f)[1]=2);
6
but it's not efficient when f has many variables. I've tried to access variable x (or x~) directly, but it didn't work:
eval(f,x=2);
eval(f,x~=2);
eval(f,'x'=2);
eval(f,'x~'=2);
eval(f,`x`=2);
eval(f,`x~`=2);
eval(f,cat(x,`~`)=2);
since the result in all those cases was 3*x~ (not 6).
Is there a way to access a specific variable directly (i.e. without using indets) after its assumptions are cleared?
There is no direct way, if utilizing assume, without programatically extracting/converting/replacing the assumed names in the previously assigned expression.
You can store the (assumed) name in another variable, and utilize that -- even after unassigning x.
Or you can pick off the names (including previously assumed names) from f using indets -- even after unassigning x.
But both of those are awkward, and it gets more cumbersome if there are many such names.
That is one reason why some people prefer to utilize assuming instead of the assume facility.
You can construct lists/sets/sequences of the relevant assumptions, and then re-utilize those in multiple assuming instances. But the global names are otherwise left alone, and your problematic mismatch situation avoided.
Another alternative is to utilize the command Physics:-assume instead of assume.
Here's an example. Notice that the assumption that x is positive still allows some simplification that depend upon it.
restart;
Physics:-Assume(x>0);
{x::(RealRange(Open(0),
infinity))}
about(x);
Originally x, renamed x:
is assumed to be:
RealRange(Open(0),infinity)
f:=3*x;
f := 3 x
simplify(sqrt(x^2));
x
Physics:-Assume('clear'={x});
{}
about(x);
x:
nothing known about this object
eval(f, [x=2]);
6
As for handling the original example utilizing assume, and substituting in f for the (still present, assumed names), it can be done programmatically to alleviate some awkwardness with, say, a larger set of assumptions. For example,
restart;
# re-usable utility
K:=(e,p)->eval(e,
eval(map(nm->nm=parse(sprintf("%a",nm)),
indets(e,And(name,
satisfies(hasassumptions)))),
p)):
assume(x>0, y>0, t<z);
f:=3*x;
f := 3 x
g:=3*x+y-sin(t);
g := 3 x + y - sin(t)
x:='x': y:='y': t:='t':
K(f,[x=2]);
6
K(g,[x=2,y=sqrt(2),t=11]);
(1/2)
6 + 2 - sin(11)
In the Z specifications language, is the colon symbol ':' a mere variation of the set membership symbol '∈'? Can they always be used interchangeably? In particular, are the following expressions legal in Z?
IMHO, No.
Although every set can be used as a type [source: page 11], the syntax for declaring a variable x of type T is well-defined and it unambiguously uses only the colon symbol : [source: page 15].
The subtle distinction between the notion of Type and the notion of membership-of is that a variable x can be only of one given Type, but it may belong to (possibly infinitely) many Sets.
Since this type of writing qualifies as an abuse of notation, you may be required to include a disclaimer in your research paper/document that clarifies the notation you are using, and what is the advantage in doing so (I see none). On this regard, I would invite you to look at the research literature and at your peers and try to stick to the convention used by the surrounding environment.
This
{ x ∈ Z | x < 100 }
does not respect the syntax for set comprehensions:
{ x : T | pred(x) ● expr(x) }
The set of all elements that result from evaluating
expr(x) for all x of type T for which pred(x)
holds.
When expr(x) is equal to x, i.e. when we return
the element itself, we can omit expr(x) and write
{ x : T | pred(x) }
[source: pages 7,8]
This
λx ∈ Z • x + 1
does not respect the syntax for lambda functions [source: page 24]:
λa : S | p • e
Im trying to make a n-nested loop method in Julia
function fun(n::Int64)
#nloops n i d->1:3 begin\n
#nexprs n j->(print(i_j))\n
end
end
But the #nloops definition is limited to
_nloops(::Int64, ::Symbol, ::Expr, ::Expr...)
and I get the error
_nloops(::Symbol, ::Symbol, ::Expr, ::Expr)
Is there any way to make this work? Any help greatly appreciated
EDIT:
What I ended up doing was using the combinations method
For my problem, I needed to get all k-combinations of indices to pull values from an array, so the loops would had to look like
for i_1 in 1:100
for i_2 in i_1:100
...
for i_k in i_[k-1]:100
The number of loops needs to be a compile-time constant – a numeric literal, in fact: the code generated for the function body cannot depend on a function argument. Julia's generated functions won't help either since n is just a plain value and not part of the type of any argument. Your best bet for having the number of nested loops depend on a runtime value like n is to use recursion.
In julia-0.4 and above, you can now do this:
function fun(n::Int)
for I in CartesianRange(ntuple(d->1:3, n))
#show I
end
end
In most cases you don't need the Base.Cartesian macros anymore (although there are still some exceptions). It's worth noting that, just as described in StefanKarpinski's answer, this loop will not be "type stable" because n is not a compile-time constant; if performance matters, you can use the "function barrier technique." See http://julialang.org/blog/2016/02/iteration for more information about all topics related to these matters.
Suppose one needs to select the real solutions after solving some equation.
Is this the correct and optimal way to do it, or is there a better one?
restart;
mu := 3.986*10^5; T:= 8*60*60:
eq := T = 2*Pi*sqrt(a^3/mu):
sol := solve(eq,a);
select(x->type(x,'realcons'),[sol]);
I could not find real as type. So I used realcons. At first I did this:
select(x->not(type(x,'complex')),[sol]);
which did not work, since in Maple 5 is considered complex! So ended up with no solutions.
type(5,'complex');
(* true *)
Also I could not find an isreal() type of function. (unless I missed one)
Is there a better way to do this that one should use?
update:
To answer the comment below about 5 not supposed to be complex in maple.
restart;
type(5,complex);
true
type(5,'complex');
true
interface(version);
Standard Worksheet Interface, Maple 18.00, Windows 7, February
From help
The type(x, complex) function returns true if x is an expression of the form
a + I b, where a (if present) and b (if present) are finite and of type realcons.
Your solutions sol are all of type complex(numeric). You can select only the real ones with type,numeric, ie.
restart;
mu := 3.986*10^5: T:= 8*60*60:
eq := T = 2*Pi*sqrt(a^3/mu):
sol := solve(eq,a);
20307.39319, -10153.69659 + 17586.71839 I, -10153.69659 - 17586.71839 I
select( type, [sol], numeric );
[20307.39319]
By using the multiple argument calling form of the select command we here can avoid using a custom operator as the first argument. You won't notice it for your small example, but it should be more efficient to do so. Other commands such as map perform similarly, to avoid having to make an additional function call for each individual test.
The types numeric and complex(numeric) cover real and complex integers, rationals, and floats.
The types realcons and complex(realcons) includes the previous, but also allow for an application of evalf done during the test. So Int(sin(x),x=1..3) and Pi and sqrt(2) are all of type realcons since following an application of evalf they become floats of type numeric.
The above is about types. There are also properties to consider. Types are properties, but not necessarily vice versa. There is a real property, but no real type. The is command can test for a property, and while it is often used for mixed numeric-symbolic tests under assumptions (on the symbols) it can also be used in tests like yours.
select( is, [sol], real );
[20307.39319]
It is less efficient to use is for your example. If you know that you have a collection of (possibly non-real) floats then type,numeric should be an efficient test.
And, just to muddy the waters... there is a type nonreal.
remove( type, [sol], nonreal );
[20307.39319]
The one possibility is to restrict the domain before the calculation takes place.
Here is an explanation on the Maplesoft website regarding restricting the domain:
4 Basic Computation
UPD: Basically, according to this and that, 5 is NOT considered complex in Maple, so there might be some bug/error/mistake (try checking what may be wrong there).
For instance, try putting complex without quotes.
Your way seems very logical according to this.
UPD2: According to the Maplesoft Website, all the type checks are done with type() function, so there is rather no isreal() function.
I am trying to implement a polynomial class with fortran 2003, with overloaded arithmetic operations and assignments. The derived type maintains allocatable list of term definitions and coefficients, like this
type polynomial
private
type(monomial),dimension(:),allocatable :: term
double precision,dimension(:),allocatable :: coef
integer :: nterms=0
contains
...
end type polynomial
interface assignment(=)
module procedure :: polynomial_assignment
end interface
...
contains
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(???) :: lhs
type(polynomial),intent(in) :: rhs
...
I had to make it elemental because this is intended to be used as matrices of polynomials. That does work, for the most cases at least. However, I somehow got myself into concerns about self-assignment here. One can simply check the pointers to see if things are the same in C++, but it doesn't seem to be an option in Fortran. However the compiler do detect the self-assignment and gave me a warning. (gfortran 4.9.0)
When I have intent(out) for lhs, the allocatable entries for both lhs and rhs appeared to be deallocated on entry to the subroutine, which made sense since they were both p, and an intent(out) argument would first be finalized.
Then I tried to avoid the deallocation with an intent(inout), and check self-assignment by modifying one field in the lhs output
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(inout) :: lhs
type(polynomial),intent(in) :: rhs
lhs%nterms=rhs%nterms-5
if(lhs%nterms==rhs%nterms)then
lhs%nterms=rhs%nterms+5
return
end if
lhs%nterms=rhs%nterms
Well, now this is what surprised me. When i do
p=p
It didn't make the test and proceeded, giving me a polynomial with 0 terms but no memory violations. Confused, I printed lhs%nterms and rhs%nterms inside the assignment, only to find that they are different!
What is even more confusing is that when I did the same thing with
call polyn_assignment(p,p)
It works perfectly and detected that both arguments are the same. I am puzzled how an interface of a subroutine can run differently from the subroutine itself.
Is there something special about assignment in Fortran 2003 that I've missed?
(First time to ask a question here. Please correct me if i didn't do it right.)
If you have a statement a = b that invokes defined assignment via a subroutine sub, the assignment statement is equivalent to call sub(a, (b)). Note the parentheses - the right hand side argument is the result of evaluating a parenthesised expression and is therefore not conceptually the same object as b. See F2008 12.4.3.4.3 for details.
Consequently, a = a is equivalent to call sub(a, (a)). The two arguments are not aliased. It is different from call sub(a,a), the latter may (depending on the specifics of the internals of sub, including dummy argument attributes) break Fortran's argument aliasing rules (e.g. in your example, a statement such as call polyn_subroutine(a,a) is illegal).