3

I would like to simplify some database notation, and I'm doing some tests with UpValues for that.

For example, if I set this Upvalue fot tab1:

tab1 /: tab1.column1 = 1

When I evaluate

tab1.column1

I get 1 as expected. But if later I set column1 = "x", when I evaluate it again, I get tab1."x" instead of 1 as I need.

There is some way that I can change this behavior? So I could get 1 and prevent variables name conflict?

Update

To avoid misinterpretation here is the evaluation sequence.

Quit the kernel and evaluate:

tab1 /: tab1.column1 = 1;
column1 = "x";
tab1.column1 

The result is tab1."x" in the first evaluation.

Murta
  • 26,275
  • 6
  • 76
  • 166
  • I get 1, as expected, in version 9.0.0 (Windows Vista). – kglr Feb 04 '13 at 00:00
  • @kguler Hi.. Strange behavior... see post update. – Murta Feb 04 '13 at 00:21
  • I can't reproduce either of the reported behaviors. On OS X, V9.0.0, I get tab1."x" for all evaluations of tab1.column1. That's what I would expect because I think the ownvalue for column1 is in inserted into Dot before tab1 is checked for upvalues. – m_goldberg Feb 04 '13 at 00:59
  • @m_goldberg it's this. The if you do Unprotect@Dot; SetAttributes[Dot, HoldAll] it will works as I need, but now I'm looking for some way to do that without use Unprotect@Dot (I don't know if it's possible). Another test is tab1.Unevaluated@column1. Tks. – Murta Feb 04 '13 at 01:06
  • @Murta Very closely related (perhaps a duplicate?): http://mathematica.stackexchange.com/questions/4161/short-syntax-for-accessing-systemutilitieshashtableadd-and-systemutilitiesha The trick is to create a localized scope for the modifications using InternalInheritedBlock` – Ajasja Feb 04 '13 at 12:58

3 Answers3

4

You could do:

Unprotect[Dot];
SetAttributes[Dot, HoldAll]

Then

   tab1 /: tab1.column1 = 1 ;
   column1 = "x";
   tab1.column1

returns 1

Is this what you want?

Rolf Mertig
  • 17,172
  • 1
  • 45
  • 76
  • Yes!.. it's this! But it's safe? There is some way to do it in the moment of define the UpValue, (without change Dot)? – Murta Feb 04 '13 at 00:31
  • I was thinking in something like tab1 /: Dot[tab1, x_] := Dot[tab1, Unevaluated@x] but it does not works. – Murta Feb 04 '13 at 00:53
  • 1
    It's safe. But why do you really want to do this? I would rather invent new Mathematica or DatabaseLink - like functions to do what you want. – Rolf Mertig Feb 04 '13 at 01:10
  • You can see the application in the Updated part of this post. I really don't like the way I handle database table today. I'm seeking some way to make the code better. – Murta Feb 04 '13 at 01:23
  • 1
    Hi Rolf!.. I just discovery that Unprotect Dot is dangerous. Today I discovery that DateRange do not work if we set SetAttributes[Dot, HoldAll] – Murta Feb 04 '13 at 14:07
  • Hi Murta. OK. You could try to use ** instead, i.e., NonCommutativeMultiply – Rolf Mertig Feb 04 '13 at 14:09
4

You could introduce your own notation. Something like the following.

SetAttributes[qualifed, HoldAll]
Needs["Notation`"]
Notation[ParsedBoxWrapper[
  RowBox[{"u_", "∘", "v_"}]] \[DoubleLongLeftRightArrow] 
   ParsedBoxWrapper[RowBox[{"qualifed", "[", RowBox[{"u_", ",", "v_"}], "]"}]]]
TagSetDelayed[qualifed, qualifed[u_, v_] = val_, TagSet[u, qualifed[u, v], val]]

tab1∘col1 = 1; tab1∘col1

1

col1 = 42; tab1∘col1

1

tab1∘col1 = 42; tab1∘col1

42

I'm using \[SmallCircle] () in place of dot (.). It can be entered with [esc]sc[esc]. I've tested this only a little. I'm not sure it's foolproof.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
2

Are you sure you're not looking for this:

tab1 /: tab1.column1_ := 1;

That is whatever column1 binds to rather than the literal column1?

this way

tab1."x"

evaluates to

1

Carlo
  • 1,171
  • 9
  • 12
  • Today I know that use columns names as symbol instead of strings create a lot of troubles. But tks +1 – Murta Dec 31 '14 at 10:36
  • But this approach would also work with symbols: tab1.anothercolumn evaluates to 1 as well – Carlo Dec 31 '14 at 10:38