Differing namespace behavior

I can create two namespaces, .a and .b:q)\d .aq.a)f:{g}q.a)g:{showhello}q.a)\d .q).b.f:{g[]}q).b.g:{showhello}The namespaces appear to be identical, but internally they’re not:q).Q.s1[.a]~.Q.s1 .b1bq).a~.b0bAnd when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:q).a.f`helloq).b.f{g}'gWhy the difference? Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?Thanks,Rob

You can have a look at the internals of the function:

http://code.kx.com/wiki/Reference/value
(at the valuing of a function part)

You can see the differences at the (context;globals) part of the result with this quick approach:

contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]

    cont glob
.a.f a    g
.b.f       g

Telling you .b.f is looking for g in the root context and hence your error.

HTH,
Sean

Perfect. Thanks!

 

28.11.2016, 10:54, “Sean O’Hagan” <sohagan@firstderivatives.com>:

You can have a look at the internals of the function:

http://code.kx.com/wiki/Reference/value
(at the valuing of a function part)

You can see the differences at the (context;globals) part of the result with this quick approach:

contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]

    cont glob
.a.f a    g
.b.f       g

Telling you .b.f is looking for g in the root context and hence your error.

HTH,
Sean

On Monday, November 28, 2016 at 10:12:47 AM UTC, Rob Smith wrote:

I can create two namespaces, .a and .b:

q)\d .a
q.a)f:{g}
q.a)g:{showhello} q.a)\d . q).b.f:{g[]} q).b.g:{showhello}

The namespaces appear to be identical, but internally they’re not:

q).Q.s1[.a]~.Q.s1 .b
1b
q).a~.b
0b

And when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:

q).a.f
`hello
q).b.f
{g}
'g

Why the difference?  Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?

Thanks,
Rob

 


Submitted via Google Groups

Look at this as link as well- http://code.kx.com/wiki/JB:QforMortals/workspace\_organization#Functions\_and\_Contexts

It has some good examples.

From the link - “The context of an unqualfied global variable in a function is the context in which the function is defined, not the context in which it is evaluated.”



On Monday, 28 November 2016 11:35:54 UTC, Rob Smith wrote:

Perfect. Thanks!

 

28.11.2016, 10:54, “Sean O’Hagan” <soh…@firstderivatives.com>:

You can have a look at the internals of the function:

http://code.kx.com/wiki/Reference/value
(at the valuing of a function part)

You can see the differences at the (context;globals) part of the result with this quick approach:

contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]

    cont glob
.a.f a    g
.b.f       g

Telling you .b.f is looking for g in the root context and hence your error.

HTH,
Sean

Thanks. So is there any way to modify a table in a non-default context using its unqualified name? For example, say I have two tables and a function defined in the .ex context: \d .ex asks:bids:([]buy:0#1b; id:0#0Ng; px:0#0n; qty:0#0n) addOrder:{$[x`buy;`bids;`asks]upsert x} When I run addOrder `buy`id`px`qty!(1b;rand 0Ng;12.34;100f) the order isn't upserted into .ex.bids. Even though the function is defined in the .ex context, bids is modified in the default context.

 

28.11.2016, 15:03, “RAHUL ASATI” <rahul.asati04@gmail.com>:

Look at this as link as well- http://code.kx.com/wiki/JB:QforMortals/workspace_organization#Functions_and_Contexts

It has some good examples.

 

From the link - “The context of an unqualfied global variable in a function is the context in which the function is defined, not the context in which it is evaluated.”

 

On Monday, 28 November 2016 11:35:54 UTC, Rob Smith wrote:

Perfect. Thanks!

 

28.11.2016, 10:54, “Sean O’Hagan” <soh…@firstderivatives.com>:

You can have a look at the internals of the function:

http://code.kx.com/wiki/Reference/value
(at the valuing of a function part)

You can see the differences at the (context;globals) part of the result with this quick approach:

contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]

    cont glob
.a.f a    g
.b.f       g

Telling you .b.f is looking for g in the root context and hence your error.

HTH,
Sean

On Monday, November 28, 2016 at 10:12:47 AM UTC, Rob Smith wrote:

I can create two namespaces, .a and .b:

q)\d .a
q.a)f:{g}
q.a)g:{showhello} q.a)\d . q).b.f:{g[]} q).b.g:{showhello}

The namespaces appear to be identical, but internally they’re not:

q).Q.s1[.a]~.Q.s1 .b
1b
q).a~.b
0b

And when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:

q).a.f
`hello
q).b.f
{g}
'g

Why the difference?  Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?

Thanks,
Rob

 


Submitted via Google Groups

Which version are you using? If you run that from .ex context that should work. Its working for me.

Another behavior to note is that variables referenced using backtick inside function are parsed as constants  (use value on function to get details) and constants are read/write in the context in which function is executing.

Ex:

q) a:2   // root context

q) \d .ex

q.ex)  a: 3  // .ex context

q.ex) f:{get[`a]+1}  

q.ex)  f  // output - 4 (read from .e context)

q.ex)\d .

q) .ex.f  // output - 3  read from root context

Above behavior also applies to tables with backticks (ex: when used in insert/upsert commands). So make sure that function is getting executed in correct context as that could corrupt data in other workspace if there is a table with same name(and schema).

all reference to named variables are evaluated in the global context.

to modify the .ex.bids and .ex.asks tables, change your function to:

addOrder:{$[x`buy;`.ex.bids;`.ex.asks]<wbr>upsert x}<br></wbr>

or perhaps:

addOrder:{(`.ex.asks`.ex.buy x`buy)<wbr>upsert x}<br><br></wbr>

i would, however, not store data in the .ex directory. directories are for code and configuration variables

you can have a parallel 'ex' namespace to store your data:

ex.bids and ex.asks

that would allow you to create views on your data (which are not possible in directories).

I’m using 3.4 and can reproduce your example, so I don’t think it’s a bug.

 

I was expecting f to return the same result regardless of from what context it was called. When using a variable directly, as in g below, the context used for variable lookups is always that in which the function was defined. But I guess that is not possible when using a variable by referencing its symbol name.

 

So if I want to modify a table defined in a non-default context using a function that may be called from another context, I must reference the table’s context explicitly (as in h below), even if the function were defined in the table’s context.

 

q)a:2 q)\d .ex q.ex)a:3 q.ex)f:{get[`a]+1} q.ex)g:{a+1}

q.ex)h:{get[`.ex.a]+1} q.ex)f 4 q.ex)g 4

q.ex)h

4 q.ex)\d .  q).ex.f 3 q).ex.g 4

q).ex.h

4

 

It’s not that big a deal, but the reason I wanted to avoid specifying the context in the function is for code reuse. For example, if I wanted to run a script originally written to use the .ex context using the default context, I would need to modify every function that references a global table by name.

 

Thanks,

Rob

 

29.11.2016, 12:02, “RAHUL ASATI” <rahul.asati04@gmail.com>:

Which version are you using? If you run that from .ex context that should work. Its working for me.

 

Another behavior to note is that variables referenced using backtick inside function are parsed as constants  (use value on function to get details) and constants are read/write in the context in which function is executing.

 

Ex:

 

q) a:2   // root context

q) \d .ex

q.ex)  a: 3  // .ex context

q.ex) f:{get[`a]+1}  

q.ex)  f  // output - 4 (read from .e context)

q.ex)\d .

q) .ex.f  // output - 3  read from root context

 

Above behavior also applies to tables with backticks (ex: when used in insert/upsert commands). So make sure that function is getting executed in correct context as that could corrupt data in other workspace if there is a table with same name(and schema).

On Tuesday, 29 November 2016 05:52:01 UTC, Rob Smith wrote:

Thanks. So is there any way to modify a table in a non-default context using its unqualified name? For example, say I have two tables and a function defined in the .ex context: \d .ex asks:bids:(buy:0#1b; id:0#0Ng; px:0#0n; qty:0#0n) addOrder:{$[x`buy;`bids;`asks]upsert x} When I run addOrder `buy`id`px`qty!(1b;rand 0Ng;12.34;100f) the order isn’t upserted into .ex.bids. Even though the function is defined in the .ex context, bids is modified in the default context.

 

28.11.2016, 15:03, “RAHUL ASATI” <rahul…@gmail.com>:

Look at this as link as well- http://code.kx.com/wiki/JB:QforMortals/workspace_organization#Functions_and_Contexts

It has some good examples.

 

From the link - “The context of an unqualfied global variable in a function is the context in which the function is defined, not the context in which it is evaluated.”

 

On Monday, 28 November 2016 11:35:54 UTC, Rob Smith wrote:

Perfect. Thanks!

 

28.11.2016, 10:54, “Sean O’Hagan” <soh…@firstderivatives.com>:

You can have a look at the internals of the function:

http://code.kx.com/wiki/Reference/value
(at the valuing of a function part)

You can see the differences at the (context;globals) part of the result with this quick approach:

contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]

    cont glob
.a.f a    g
.b.f       g

Telling you .b.f is looking for g in the root context and hence your error.

HTH,
Sean

On Monday, November 28, 2016 at 10:12:47 AM UTC, Rob Smith wrote:

I can create two namespaces, .a and .b:

q)\d .a
q.a)f:{g}
q.a)g:{showhello} q.a)\d . q).b.f:{g[]} q).b.g:{showhello}

The namespaces appear to be identical, but internally they’re not:

q).Q.s1[.a]~.Q.s1 .b
1b
q).a~.b
0b

And when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:

q).a.f
`hello
q).b.f
{g}
'g

Why the difference?  Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?

Thanks,
Rob

 


Submitted via Google Groups

Sorry, the formatting of my example got screwed up:q)a:2q)\d .exq.ex)a:3q.ex)f:{get[a]+1}q.ex)g:{a+1}q.ex)h:{get[.ex.a]+1}q.ex)f4q.ex)g4q.ex)h4q.ex)\d .q).ex.f3q).ex.g4q).ex.h429.11.2016, 12:38, “Rob Smith” :> I’m using 3.4 and can reproduce your example, so I don’t think it’s a bug.>> I was expecting f to return the same result regardless of from what context it was called. When using a variable directly, as in g below, the context used for variable lookups is always that in which the function was defined. But I guess that is not possible when using a variable by referencing its symbol name.>> So if I want to modify a table defined in a non-default context using a function that may be called from another context, I must reference the table’s context explicitly (as in h below), even if the function were defined in the table’s context.>> q)a:2 q)\d .ex q.ex)a:3 q.ex)f:{get[a]+1} q.ex)g:{a+1}&gt; q.ex)h:{get[.ex.a]+1} q.ex)f 4 q.ex)g 4> q.ex)h> 4 q.ex)\d . q).ex.f 3 q).ex.g 4> q).ex.h> 4>> It’s not that big a deal, but the reason I wanted to avoid specifying the context in the function is for code reuse. For example, if I wanted to run a script originally written to use the .ex context using the default context, I would need to modify every function that references a global table by name.>> Thanks,> Rob>> 29.11.2016, 12:02, “RAHUL ASATI” <rahul.asati04>:>> Which version are you using? If you run that from .ex context that should work. Its working for me.>>>> Another behavior to note is that variables referenced using backtick inside function are parsed as constants (use value on function to get details) and constants are read/write in the context in which function is executing.>>>> Ex:>>>> q) a:2 // root context>> q) \d .ex>> q.ex) a: 3 // .ex context>> q.ex) f:{get[a]+1}&gt;&gt; q.ex) f[] // output - 4 (read from .e context)&gt;&gt; q.ex)\d .&gt;&gt; q) .ex.f[] // output - 3 read from root context&gt;&gt;&gt;&gt; Above behavior also applies to tables with backticks (ex: when used in insert/upsert commands). So make sure that function is getting executed in correct context as that could corrupt data in other workspace if there is a table with same name(and schema).&gt;&gt;&gt;&gt; On Tuesday, 29 November 2016 05:52:01 UTC, Rob Smith wrote:&gt;&gt;&gt; Thanks. So is there any way to modify a table in a non-default context using its unqualified name? For example, say I have two tables and a function defined in the .ex context: \d .ex asks:bids:([]buy:0#1b; id:0#0Ng; px:0#0n; qty:0#0n) addOrder:{$[xbuy;bids;asks]upsert x} When I run addOrder buyidpxqty!(1b;rand 0Ng;12.34;100f) the order isn’t upserted into .ex.bids. Even though the function is defined in the .ex context, bids is modified in the default context.>>>>>> 28.11.2016, 15:03, “RAHUL ASATI” <rahul…>:>>>> Look at this as link as well- http://code.kx.com/wiki/JB:QforMortals/workspace_organization#Functions_and_Contexts&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; It has some good examples.>>>>>>>> From the link - “The context of an unqualfied global variable in a function is the context in which the function is defined, not the context in which it is evaluated.”>>>>>>>> On Monday, 28 November 2016 11:35:54 UTC, Rob Smith wrote:>>>>> Perfect. Thanks!>>>>>>>>>> 28.11.2016, 10:54, “Sean O’Hagan” <soh…>:>>>>>> You can have a look at the internals of the function:>>>>>>>>>>>> http://code.kx.com/wiki/Reference/value&gt;&gt;&gt;&gt;&gt;&gt; (at the valuing of a function part)>>>>>>>>>>>> You can see the differences at the (context;globals) part of the result with this quick approach:>>>>>>>>>>>> contglob!/:l!raze each r[;where not (~'). r:(get get@)each l:.a.f.b.f]>>>>>> | cont glob>>>>>> ----| --------->>>>>> .a.f| a g>>>>>> .b.f| g>>>>>>>>>>>> Telling you .b.f is looking for g in the root context and hence your error.>>>>>>>>>>>> HTH,>>>>>> Sean>>>>>>>>>>>> On Monday, November 28, 2016 at 10:12:47 AM UTC, Rob Smith wrote:>>>>>>> I can create two namespaces, .a and .b:>>>>>>>>>>>>>> q)\d .a>>>>>>> q.a)f:{g}>>>>>>> q.a)g:{showhello}&gt;&gt;&gt;&gt;&gt;&gt;&gt; q.a)\d .&gt;&gt;&gt;&gt;&gt;&gt;&gt; q).b.f:{g[]}&gt;&gt;&gt;&gt;&gt;&gt;&gt; q).b.g:{showhello}>>>>>>>>>>>>>> The namespaces appear to be identical, but internally they’re not:>>>>>>>>>>>>>> q).Q.s1[.a]~.Q.s1 .b>>>>>>> 1b>>>>>>> q).a~.b>>>>>>> 0b>>>>>>>>>>>>>> And when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:>>>>>>>>>>>>>> q).a.f>>>>>>> `hello>>>>>>> q).b.f>>>>>>> {g}>>>>>>> 'g>>>>>>>>>>>>>> Why the difference? Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?>>>>>>>>>>>>>> Thanks,>>>>>>> Rob>>>>>>>>>>>> –>>>>>>

Submitted via Google Groups</soh…></rahul…></rahul.asati04>

Ok, last post on this topic..Nick suggested not storing data in namespaces, which seems like an unfortunate sacrifice, but I can work around that. But now I’m seeing that even functions don’t seem to work well when defined in a namespace. For example:q)\d .nsq.ns)rnd2:{(“j”$100f*x)%100f}eachq.ns)f:{update qty:rnd2 qty+1f from (qty:1?1f)}q.ns)\d .q).ns.f{update qty:rnd2 qty+1f from (qty:10?1f)}‘rnd2I’m unable to use the rnd2 function in a select/update statement because internally kdb is looking up the function by name which looks for it in the calling context rather than the function’s definition context.Am I not using namespaces as they were intended? They don’t seem to be useful beyond trivial use cases. Is there a better approach to creating self-contained units of code/data when running everything in a single process?29.11.2016, 12:46, “Rob Smith” :> Sorry, the formatting of my example got screwed up:>> q)a:2> q)\d .ex> q.ex)a:3> q.ex)f:{get[a]+1}&gt; q.ex)g:{a+1}&gt; q.ex)h:{get[.ex.a]+1}> q.ex)f> 4> q.ex)g> 4> q.ex)h> 4> q.ex)\d .> q).ex.f> 3> q).ex.g> 4> q).ex.h> 4>> 29.11.2016, 12:38, “Rob Smith” :>> I’m using 3.4 and can reproduce your example, so I don’t think it’s a bug.>>>> I was expecting f to return the same result regardless of from what context it was called. When using a variable directly, as in g below, the context used for variable lookups is always that in which the function was defined. But I guess that is not possible when using a variable by referencing its symbol name.>>>> So if I want to modify a table defined in a non-default context using a function that may be called from another context, I must reference the table’s context explicitly (as in h below), even if the function were defined in the table’s context.>>>> q)a:2 q)\d .ex q.ex)a:3 q.ex)f:{get[a]+1} q.ex)g:{a+1}&gt;&gt; q.ex)h:{get[.ex.a]+1} q.ex)f 4 q.ex)g 4>> q.ex)h>> 4 q.ex)\d . q).ex.f 3 q).ex.g 4>> q).ex.h>> 4>>>> It’s not that big a deal, but the reason I wanted to avoid specifying the context in the function is for code reuse. For example, if I wanted to run a script originally written to use the .ex context using the default context, I would need to modify every function that references a global table by name.>>>> Thanks,>> Rob>>>> 29.11.2016, 12:02, “RAHUL ASATI” <rahul.asati04>:>>> Which version are you using? If you run that from .ex context that should work. Its working for me.>>>>>> Another behavior to note is that variables referenced using backtick inside function are parsed as constants (use value on function to get details) and constants are read/write in the context in which function is executing.>>>>>> Ex:>>>>>> q) a:2 // root context>>> q) \d .ex>>> q.ex) a: 3 // .ex context>>> q.ex) f:{get[a]+1}&gt;&gt;&gt; q.ex) f[] // output - 4 (read from .e context)&gt;&gt;&gt; q.ex)\d .&gt;&gt;&gt; q) .ex.f[] // output - 3 read from root context&gt;&gt;&gt;&gt;&gt;&gt; Above behavior also applies to tables with backticks (ex: when used in insert/upsert commands). So make sure that function is getting executed in correct context as that could corrupt data in other workspace if there is a table with same name(and schema).&gt;&gt;&gt;&gt;&gt;&gt; On Tuesday, 29 November 2016 05:52:01 UTC, Rob Smith wrote:&gt;&gt;&gt;&gt; Thanks. So is there any way to modify a table in a non-default context using its unqualified name? For example, say I have two tables and a function defined in the .ex context: \d .ex asks:bids:([]buy:0#1b; id:0#0Ng; px:0#0n; qty:0#0n) addOrder:{$[xbuy;bids;asks]upsert x} When I run addOrder buyidpxqty!(1b;rand 0Ng;12.34;100f) the order isn’t upserted into .ex.bids. Even though the function is defined in the .ex context, bids is modified in the default context.>>>>>>>> 28.11.2016, 15:03, “RAHUL ASATI” <rahul…>:>>>>> Look at this as link as well- http://code.kx.com/wiki/JB:QforMortals/workspace_organization#Functions_and_Contexts&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; It has some good examples.>>>>>>>>>> From the link - “The context of an unqualfied global variable in a function is the context in which the function is defined, not the context in which it is evaluated.”>>>>>>>>>> On Monday, 28 November 2016 11:35:54 UTC, Rob Smith wrote:>>>>>> Perfect. Thanks!>>>>>>>>>>>> 28.11.2016, 10:54, “Sean O’Hagan” <soh…>:>>>>>>> You can have a look at the internals of the function:>>>>>>>>>>>>>> http://code.kx.com/wiki/Reference/value&gt;&gt;&gt;&gt;&gt;&gt;&gt; (at the valuing of a function part)>>>>>>>>>>>>>> You can see the differences at the (context;globals) part of the result with this quick approach:>>>>>>>>>>>>>> contglob!/:l!raze each r[;where not (~’). r:(get get@)each l:.a.f.b.f]>>>>>>> | cont glob>>>>>>> ----| --------->>>>>>> .a.f| a g>>>>>>> .b.f| g>>>>>>>>>>>>>> Telling you .b.f is looking for g in the root context and hence your error.>>>>>>>>>>>>>> HTH,>>>>>>> Sean>>>>>>>>>>>>>> On Monday, November 28, 2016 at 10:12:47 AM UTC, Rob Smith wrote:>>>>>>>> I can create two namespaces, .a and .b:>>>>>>>>>>>>>>>> q)\d .a>>>>>>>> q.a)f:{g}>>>>>>>> q.a)g:{showhello}&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; q.a)\d .&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; q).b.f:{g[]}&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; q).b.g:{showhello}>>>>>>>>>>>>>>>> The namespaces appear to be identical, but internally they’re not:>>>>>>>>>>>>>>>> q).Q.s1[.a]~.Q.s1 .b>>>>>>>> 1b>>>>>>>> q).a~.b>>>>>>>> 0b>>>>>>>>>>>>>>>> And when I call .a.f, it knows to look for g in the .a namespace, but .b.f tries to find g in the global namespace:>>>>>>>>>>>>>>>> q).a.f>>>>>>>> `hello>>>>>>>> q).b.f>>>>>>>> {g}>>>>>>>> 'g>>>>>>>>>>>>>>>> Why the difference? Is there any way to distinguish between the two behaviors (other than knowing how the namespaces were created)?>>>>>>>>>>>>>>>> Thanks,>>>>>>>> Rob>>>>>>>>>>>>>> –>>>>>>>

Submitted via Google Groups</soh…></rahul…></rahul.asati04>

Hi Rob,

For your first example - there are workarounds(do not forget nick’s notes though)

.e.g

\d .ex
asks:bids:([]buy:0#1b; id:0#0Ng; px:0#0n; qty:0#0n)
addOrder:{(` sv `,get[.z.s][3;0],$[x`buy;`bids;`asks])upsert x}
\d .

//now below will upsert to .ex.bids as you require
.ex.addOrder`buy`id`px`qty!(1b;rand 0Ng;12.34;100f)

for your last example you should read about masking here http://code.kx.com/wiki/Reference/select#scope
and again use ‘value’  to your advantage..shown below

\d .ns
rnd2:{(“j”$100f*x)%100f}each
f:{update qty:rnd2 qty+1f from (qty:1?1f)}
f2:{{update qty:x qty+1f from (qty:1?1f)}rnd2}
\d .
.ns.f
{update qty:rnd2 qty+1f from (qty:1?1f)}
'rnd2
\
.ns.f2
qty

1.58
//use value to see what’s going on…
l!.[;(::;3)]get each .ns l:ff2
f | ,ns f2| ns`rnd2

HTH,
Sean

using q-sql adds a convenient syntax, but is not always necessary.

best practices would dictate that your namespace should have utility functions that apply to generic data with no knowledge of table column names.  this would allow anyone to use your library regardless of how they decide to name their columns.

the tables should also be passed in as arguments so the user can use them on stack variables within functions.

agreed that there are limitations on how namespace are managed, but i’ve rarely found this to be a problem. if you read the code from Q Tips, you will see that functions are used across namespaces without issue.

note you can generalize your code a bit by making a rnd function

rnd:{x*“j”$y%x}

rnd2:rnd[.01]

also note that q is a vector language and that there is no need to use ‘each’ in your example above.