When does : (amend) not modify its first argument?
Short answer: When 1) projected or 2) modified by an adverb, e.g., :/: :: or :’
Normally, the : (amend) function is used to assign a value to a name:
q)foo: 47
q)foo
47
q)
Like other built-in functions that take two arguments, : (amend) can be called using either infix notation (as above) or function call notation:
q):[foo; 747]
q)foo
747
q)
Note that : (amend) displays its special semantics (which it shares with assignments in all strict languages) of not evaluating its first argument when that argument is simply a name, regardless of whether : (amend) is invoked infix or functionally.
q)delete bar from `. / make sure bar is not defined
q):[bar; 42]
q)bar
42
q)
On the other hand, : (amend) does evaluate its first argument when that argument is an expression, but : (amend) still produces l-values when it does so:
q)list: 0 1 2 3
q)list[0]: 47
q)list
47 1 2 3
q):[list 1 2 3; 10 20 30]
q)list
47 10 20 30
q)
Based on the previous examples, you might be tempted create a projection from : (amend) and a left-hand side, but it turns out you can’t:
q):[foo]
'foo
q)
It is possible to close the first argument to : (amend), but the resulting projection is no longer an assignment; it is an identity function:
q)foo: 42
q)(:[foo])[47]
47
q)foo
42
q)
In fact, the value attached to the first argument of : (amend) is irrelevant:
q)(:[`xyzzy])[47]
47
q)
Closing the second argument will cause : (amend) to return the same value always:
q)f: :[; 3] / bind the 2nd argument
q)f 18 / no matter what we pass
3
q)f "hello" / f will always return 3
3
q)
The other case when : (amend) does not perform assignment is when it is modified by an adverb:
q)list1: 0 1 2 3
q)list2: 4 5 6 7
q)(list1; list2) :\: 10 20 30 40 / we get the rhs
10 20 30 40 / once for each list
10 20 30 40
q)list1 / neither list
0 1 2 3
q)list2 / has been modified
4 5 6 7
q)list2 :/: 0 1 2 3
0 1 2 3
q)list1[0 1 2 3] :' 10 20 30 40
10 20 30 40
q)