简体   繁体   中英

“APL Object Notation” in Dyalog APL

How to convert any Dyalog APL value to a character vector that could be passed to to get the same value?

How this is expected to look like:

      x←2 3⍴⍳6
      x←1,⊂x
      x←x,⊂'foo'
      y←desired_function x
      DPX y
┌→─────────────────┐
│1,(⊂2 3⍴⍳6),⊂'foo'│
└──────────────────┘
      x≡⍎y
1

Update

The idea is to convert a value to a human-editable APL source code to be able to insert it to a unit test function, when a new problematic scenario has been found. I want those test scenarios to be in APL source code, not in files, because in a framework I work with, source code is nicely managed by a version control system, while files are not. And I want it to be human-editable, not just serialized, to make it easier to amend existing test scenarios when arguments/results change.

In my opinion, Execute & "transfer form" are not optimal solutions, for a number of reasons:

  • Complex structures quickly become difficult to read
  • Execute is a relatively heavy / inefficient tool to invoke, compare to other solutions
  • If you are not careful you open yourself up to "injection" attacks, malicious code in files that are supposed to contain constants but are being executed when your application starts.

Depending on what your data looks like, JSON might be a nice way to go - it is a format designed just for this:

In Dyalog 15.0:

       fromJSON←7159⌶ ⋄ toJSON←7160⌶ 
       (namespace←⎕NS '').life←42
       toJSON (⍳4) 'Hello' namespace
[[1,2,3,4],"Hello",{"life":42}]

The downside of JSON is that it cannot represent higher dimensional arrays. So you'll need to massage things a little if you need matrices:

       toJSON ↓3 4⍴⍳12 
[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
       ↑fromJSON '[[1,2,3],[5,6,7]]'
1 2 3
5 6 7

In version 16.0, to be released at the end of this month, the experimental I-Beams have become a system function ⎕JSON.

Not sure about Dyalog APL, but most other APLs have built-in functions to achieve that.

In IBM APL2 (and therefore also in GNU APL) you can use 2 ⎕TF to convert between a value (actually a variable with that value) and APL code that produces it (although not via but via another 2 ⎕TF ):

      4 ⎕CR x
┏→━━━━━━━━━━━━━━┓
┃1 ┏→━━━━┓ ┏→━━┓┃
┃  ↓1 2 3┃ ┃foo┃┃
┃  ┃4 5 6┃ ┗━━━┛┃
┃  ┗━━━━━┛      ┃
┗∊━━━━━━━━━━━━━━┛


      ⎕←text←2 ⎕TF 'x'
x←1 (2 3⍴1 2 3 4 5 6) 'foo'

      )erase x
      2 ⎕TF text
x
      4 ⎕CR x
┏→━━━━━━━━━━━━━━┓
┃1 ┏→━━━━┓ ┏→━━┓┃
┃  ↓1 2 3┃ ┃foo┃┃
┃  ┃4 5 6┃ ┗━━━┛┃
┃  ┗━━━━━┛      ┃
┗∊━━━━━━━━━━━━━━┛

In GNU APL you can also use 10 ⎕CR for that purpose. The result consists of multiple APL statements so you have to ⍎¨ over the result:

      10 ⎕CR 'x'
 x←1 00 00   ((⎕IO+1)⊃x)←2 3⍴1 2 3 4 5 6   ((⎕IO+2)⊃x)←'foo' 

      ⊃10 ⎕CR 'x'
    x←1 00 00                    
      ((⎕IO+1)⊃x)←2 3⍴1 2 3 4 5 6
      ((⎕IO+2)⊃x)←'foo'          

I don't know if there is a way to do this with ⍎, but I will mention that Dyalog Version 15.0 has 2 I-Beams to Serialize and Deserialize.

http://help.dyalog.com/15.0/Content/Language/Primitive%20Operators/Serialise%20Array.htm

eg

]disp x
┌→┬─────┬───┐
│1│0 1 2│foo│
│ │3 4 5↓   │
└─┴~───→┴──→┘

   y← 0(220⌶) 0(219⌶) 1(219⌶) 1(220⌶) x

  ]disp y
┌→┬─────┬───┐
│1│0 1 2│foo│
│ │3 4 5↓   │
└─┴~───→┴──→┘

      y ≡ x
1

Also, you might like to join our forums as you would reach more Dyalog APL users if you ask your question there.

http://www.dyalog.com/forum/

Regards,

Vince

⎕SE.Dyalog.Utils.repObj

For example:

      x←2 3⍴⍳6
      x←1,⊂x
      x←x,⊂'foo'
      y←⎕SE.Dyalog.Utils.repObj x
      ]Display y
┌→─────────────────────┐
│1 (2 3⍴1-⎕io-⍳6) 'foo'│
└──────────────────────┘
      x≡⍎y
1

Try it online!

Unless I am missing something, the interpreter does not provide a mechanism to do save & rebuild any possible type of variable (there's a lot of complexity with namespaces, objects, references to any of these etc.). "Serialisation" might come closest, but (a) it's not human-readable and (b) it's more an interpreter-mechanism than a tool for application-developers, so I do not even want to talk about it further - there are better ways to deal with that ;)

However, there is a user command which will allow you to do that:

]save (Object) (Filename)

so

]save x h:\temp\x

saved it to a unicode-file h:\\temp\\x.dyalog which could also be edited using any Unicode-capable editor (or even )edit h:\\temp\\x.dyalog ).

By doing

]load h:\temp\x

you can load that object into the workspace. Alternatively, use

]xyz←load h:\temp\x -noname

to assign the value to xyz instead of loading into x again.

And there is more... I assume your question is the result of wanting to be able to reproduce some data. Are you aware of the "component file system" which offers an easy way to save variables like x to files and reload them from there? Example:

{x ⎕fappend ⍵ ⋄ ⎕FUNTIE ⍵}'h:\temp\x'⎕FCREATE 0

to save x and then

{r←⎕fread ⍵,1 ⋄ ⎕FUNTIE ⍵ ⋄ r}'h:\temp\x'⎕FTIE 0

to read it again. (Disclaimer: these examples are over-simplistic because there is no error-handling in case the file you're creating already exists etc. - usually that also needs to be taken care of, but that would have been too much distraction for this little sample...)

So, finally, I think my real concern is about the context of that problem and the purpose you're trying to achieve. In my entire APL-life I have rarely seen things that were "not doable" - but sometimes the path is different than what you'd expect (knowing other languages)...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM