How to concatenate strings ?


    Mar 22 2006 | 12:02 pm
    Hi everybody, i'm a newbie in max and i'm already facing a problem :( I need to concatenate strings (symbols if you prefer) from 2 diferent lists and them send them over OSC to other applications (e.g. Eyesweb).
    For instance i've got a message box with [UUID00 UUID01 UUID02...UUIDnn] and another message box with [TLM-LUIS TLM-JOSE TLM-XPTO ...] my gold is to join these elements into a third list like [UUID00TLM-LUIS UUID01TLM-JOSE ...] and then send them over by OSC
    Can anyone help me out ? plzzzz :) Regards
    Nonon

    • Mar 22 2006 | 12:30 pm
      you can use sprintf
    • Mar 22 2006 | 12:41 pm
      Jasch has also made a lib for such things www.jasch.ch/dl/default.htm
      another good thing to do is to read the manual, and search in the forum if your question has not been asked thousands of times... or you'll soon learn what RTFM and STFW mean ;-)
      cheers vg
    • Mar 22 2006 | 12:44 pm
      On 22-Mar-2006, at 13:02, Nuno wrote:
      > For instance i've got a message box with [UUID00 UUID01 > UUID02...UUIDnn] and another message box with [TLM-LUIS TLM-JOSE > TLM-XPTO ...] my gold is to join these elements into a third list > like [UUID00TLM-LUIS UUID01TLM-JOSE ...] and then send them over by > OSC
      Look at zl (partic [zl iter]) and sprintf.
    • Mar 22 2006 | 12:58 pm
      On 22 Mar 2006, at 12:02, Nuno wrote:
      > I need to concatenate strings (symbols if you prefer) from 2 > diferent lists and them send them over OSC to other applications > (e.g. Eyesweb).
      As others have already hinted, [sprintf %s%s] will do what you want.
      However, if you're going to have arbitrary combinations of symbols, every combination symbol is going to go into Max's symbol hash table - forever. This may or may not affect performance.
      -- N.
      nick rothwell -- composition, systems, performance -- http:// www.cassiel.com
    • Mar 22 2006 | 4:17 pm
      Tnx to you all :)
      I did searched the forum with "concatenate strings" keywords and didn't found nothing...but since my net acess is so lousy i'm not sure of anything...as for the manual, i've got a printed version and stinks, no sprintf, i've started to read the pdf latest (and complete) version.
      I've checked the sprintf and i'm sure it will do fine , as for the jasch lib, well, tnxs again for the tip: it's a very cool one and i'm downloading it right now...
      Best Regards
      Nonon
    • Mar 22 2006 | 11:07 pm
      On Mar 22, 2006, at 7:58 AM, Nick Rothwell wrote:
      > As others have already hinted, [sprintf %s%s] will do what you want. > > However, if you're going to have arbitrary combinations of symbols, > every combination symbol is going to go into Max's symbol hash > table - forever. This may or may not affect performance.
      What's the rationale here for Max's implementation of symbols? This doesn't make much sense to me.
      - John
    • Mar 22 2006 | 11:14 pm
      On 22 Mar 2006, at 23:07, John Nowak wrote:
      > What's the rationale here for Max's implementation of symbols? This > doesn't make much sense to me.
      You mean, the rationale for permanently hashing them?
      Fast lookup and comparison. Max uses symbols for ... well, everything, really.
      -- N.
      nick rothwell -- composition, systems, performance -- http:// www.cassiel.com
    • Mar 23 2006 | 10:27 am
      Further unto: string comparison is slow. Comparing pointer addresses is fast. We can be talking as much as factor 100 here. More typically maybe factor 20 or so, but that's still a big difference. Furthermore, in the late 1980s this had to run on 68000s and 68020s at 8 MHz.
      Miller's implementation of symbols was puredead brilliant. Still is.
      The downside to this strategy (that the hash table grows and grows and grows and grows and grows and grows and...) is negligible in a world of +512MB RAM.
      -- P
      -------------- http://www.bek.no/~pcastine/Litter/ ------------- Peter Castine | +--> Litter Power & Litter Bundle for Jitter |.................................................... p@castine.de | iCE: Sequencing, Recording, and Interface Building pcastine@gmx.net | for Max/MSP pcastine@bek.no | http://www.dspaudio.com/ Extremely cool 4-15@kagi.com |.................................................... | home|chez nous|wir|i nostri http://www.castine.de/
    • Mar 23 2006 | 12:34 pm
      On 23 Mar 2006, at 10:27, Peter Castine wrote:
      > The downside to this strategy (that the hash table grows and grows > and grows and grows and grows and grows and...) is negligible in a > world of +512MB RAM.
      Sure, but these days people are talking about Max/MSP for installation works which run for months at a time. (Mine clocked in five weeks of 24/7 operation, but that's modest these days.) If the code is generating several distinct symbols a second (say, by symbolising a string representation of date and time) that adds up to ... erm ... lots. (And I don't know what computational complexity we're looking at here - O(log N)? - but with a gazillion symbols that must degrade somewhat.) So, it's a bad thing to do, and I always have faint alarm bells going off whenever I see something that's potentially synthesising dynamic symbols.
      It might be nice to have some kind of built-in Max function to report symbol table size and stats (bucket sizes and the like).
      -- N.
      nick rothwell -- composition, systems, performance -- http:// www.cassiel.com
    • Mar 23 2006 | 1:37 pm
      On 23-Mar-2006, at 13:34, Nick Rothwell wrote:
      > Sure, but these days people are talking about Max/MSP for > installation works which run for months at a time.
      Point taken. Assuming you're *not* auto-rebooting once a day (which a lot of installations do for many reasons).
      Also, if the vocabulary is sufficiently limited, auto-generated symbols will start repeating before memory becomes an issue. Nuno's example:
      >> For instance i've got a message box with [UUID00 UUID01 >> UUID02...UUIDnn] and another message box with [TLM-LUIS TLM-JOSE >> TLM-XPTO ...] > could, mathematically, generate up to 45 million different symbols, which would fill up an awful lot of RAM. But if the TLM-LUIS etc. are limited to a couple of hundred names, then symbol table growth will be tractable.
      This all depends very much on the concrete application.
      > It might be nice to have some kind of built-in Max function to > report symbol table size and stats (bucket sizes and the like).
      Or if Max time-stamped symbol usage and would start flushing unused symbols at some point.
      Or if it were possible to have a non-symbolized string data type. There was a 3rd party add-in a while back that did this; JScript and Java will also allow you to munge strings without stuffing the symbol table.
      J/JS are probably the most reliable options today for avoiding symbol table explosion. If and when it's an issue.
      You're right that people should think about what they're doing if they're going to auto-generate symbols, but in a lot of cases it doesn't rate more than blue or yellow HLS status.
      -- P.
      -------------- http://www.bek.no/~pcastine/Litter/ ------------- Peter Castine | +--> Litter Power & Litter Bundle for Jitter |.................................................... p@castine.de | iCE: Sequencing, Recording, and Interface Building pcastine@gmx.net | for Max/MSP pcastine@bek.no | http://www.dspaudio.com/ Extremely cool 4-15@kagi.com |.................................................... | home|chez nous|wir|i nostri http://www.castine.de/
    • Mar 23 2006 | 5:25 pm
      I was more talking about the permanent aspect. Obviously string comparisons for everything would be dog slow (which is part of the reason we have ports in the first place rather than prepending commands to everything I'd assume). I'd think after the current branch was done (i.e. after sprintf is done sending to everything), we'd be able to kick the symbol out of the hash table, no? I'm not trying to be snarky here -- I'm genuinely curious as I'm implementing a similar system myself. I've opted instead to do *everything* via ports, which works fine as it is a text-based language, and it is very fast (every "port" is just a function pointer that takes the current "object" and the received data as arguments). Obviously using so many "ports" is not possible with the GUI paradigm, and hence we have the current system.
      Can anyone explain why we can't manage the hash table at all?
      - John
    • Mar 23 2006 | 8:06 pm
      On Mar 23, 2006, at 9:25 AM, John Nowak wrote:
      > > Can anyone explain why we can't manage the hash table at all?
      symbols need to live for the life of the application since they are matched by pointer comparison (i.e. fast). The pointer must remain the same since there is no way of determining when there are no longer any references to said symbols. One could imagine a system which uses reference counting to "attach to" or "release" a symbol, though it would require a complete max overhaul (and all supporting objects) to do so. Not likely in the near future.
      If you want to use strings (i.e. *not* symbols), you can accomplish this in a number of ways--e.g. lists of integers or single letter symbols (which would only take up a handful of symbol table slots), or jitter matrices.
      -Joshua
    • Mar 24 2006 | 9:44 am
      This thread is interesting and important, as it shows something I was never aware of...
      Joshua Kit Clayton wrote: > If you want to use strings (i.e. *not* symbols), you can accomplish > this in a number of ways--e.g. lists of integers or single letter > symbols (which would only take up a handful of symbol table slots), or > jitter matrices.
      One essential information is missing for me: where does this hashing happen and which are the objects which actually do it. There are these lftoa and atolf objects from the pluggo installers which could translate strings into numbers. But if the symbol is already in the table it wouldn't help...
      One way to control the hash table eventually would be to exchange a symbol with another one. (Not for newbies, keep it somewhere hidden in the docs.) If you know that the symbol isn't used elswhere anymore you might want to exchange it instead of creating a new entry in the table. A nice opportunity to create almost untrackable bugs... ;-)
      For real world applications outside of installations its probably not important.
      Stefan
      --
      [][] [][][] [][] [][][] [][][][][][][][][][][][][][][]
      Stefan Tiedje Klanggestalter Electronic Composition & Improvisation
      /~~~~~ \ /|() ()| ))))) )| | |( \ /// _/)/ ))))) ___/ ///
      -------------------------x---- --_____-----------|----------- --(_|_ ----|-----|-----()---- -- _|_)----|-----()----------- ----------()------------x-----
      14, Av. Pr. Franklin Roosevelt, 94320 Thiais, France Phone at CCMIX +33-1-57 42 91 09
    • Mar 24 2006 | 10:29 am
      On 24 Mar 2006, at 09:44, Stefan Tiedje wrote:
      > One essential information is missing for me: where does this > hashing happen and which are the objects which actually do it.
      A hash entry is created (or, if it exists, retreived) by any external object, or part of Max/MSP proper, which makes a kernel call to gensym () - in other words, it happens all over.
      Re: symbol exchange: the point of hash tables is that they use hash values, designed to produce as few collisions as possible; it's not possible to exchange a symbol in-place in the table. Or am I misunderstanding your suggestion?
      -- N.
      nick rothwell -- composition, systems, performance -- http:// www.cassiel.com
    • Mar 24 2006 | 11:52 am
      On 24-Mar-2006, at 10:44, Stefan Tiedje wrote: > One way to control the hash table eventually would be to exchange a > symbol with another one. (Not for newbies, keep it somewhere hidden > in the docs.) If you know that the symbol isn't used elswhere > anymore you might want to exchange it instead of creating a new > entry in the table.
      An interesting idea that, at its core, breaks almost all of the object-orientation of Max.
      Once an object passes a symbol out of an outlet, it can never "know that it isn't used elsewhere anymore". To do that, your object would have to what objects are attached and how each and every object (including 3rd party, yet-to-be-developed objects!) that receives the symbol handles it. Maybe someone is storing your object's symbols in a coll. If you destroy the hash table entry, that coll will go BOOM! and take Max down with it.
      An object can, realistically, only gauge the lifespan of a character string that it uses internally. In this case, there is probably no need to turn the string into a symbol.
      Add to this the details of hash table management--hash tables do not generally get smaller just because a couple of entries have been deleted--the idea is probably inpracticable at several levels.
      Of course, I don't know the innards of how Max manages its particular hash tables, so I may be going out on a limb with the above. But it seems a pretty stable limb.
      -- Peter
      -------------- http://www.bek.no/~pcastine/Litter/ ------------- Peter Castine +--> Litter Power & Litter Bundle for Jitter
      iCE: Sequencing, Recording & |home | chez nous| Interface Building for |bei uns | i nostri| Max/MSP Extremely cool http://www.castine.de http://www.dspaudio.com/
    • Mar 25 2006 | 11:32 am
      Nick Rothwell wrote: > A hash entry is created (or, if it exists, retreived) by any external > object, or part of Max/MSP proper, which makes a kernel call to gensym > () - in other words, it happens all over.
      The question then would be, where does it not happen. If an external has a method "anything" does it happen? or does it happen if it has a method for "symbol"? When I send a message from a message box or from sprintf, is it already in the table? Or do I have a chance to convert it with atolf...
      > Re: symbol exchange: the point of hash tables is that they use hash > values, designed to produce as few collisions as possible; it's not > possible to exchange a symbol in-place in the table. Or am I > misunderstanding your suggestion?
      Yes that was the suggestion. Well, I am happy with Millers "puredead brilliant" way of doing it as Peter explained. No real world problem here...
      Stefan
      --
      [][] [][][] [][] [][][] [][][][][][][][][][][][][][][]
      Stefan Tiedje Klanggestalter Electronic Composition & Improvisation
      /~~~~~ \ /|() ()| ))))) )| | |( \ /// _/)/ ))))) ___/ ///
      -------------------------x---- --_____-----------|----------- --(_|_ ----|-----|-----()---- -- _|_)----|-----()----------- ----------()------------x-----
      14, Av. Pr. Franklin Roosevelt, 94320 Thiais, France Phone at CCMIX +33-1-57 42 91 09
    • Mar 25 2006 | 11:55 am
      It happens everytime the kernel or an object calls gensym(), which, if you do a Find in any of the available source code for Max objects, happens frequently.
      In effect, every message you send to the inlet of a Max object, or type into a box is, at some point, converted to a symbol.
      jb
    • Mar 26 2006 | 11:48 am
      Jeremy Bernstein wrote: > In effect, every message you send to the inlet of a Max object, or type > into a box is, at some point, converted to a symbol.
      In short terms, even if I send something to atolf it will be converted because its going to its inlet. Aka no issue for patchers, only for source coders eventually.
      Stefan
      --
      [][] [][][] [][] [][][] [][][][][][][][][][][][][][][]
      Stefan Tiedje Klanggestalter Electronic Composition & Improvisation
      /~~~~~ \ /|() ()| ))))) )| | |( \ /// _/)/ ))))) ___/ ///
      -------------------------x---- --_____-----------|----------- --(_|_ ----|-----|-----()---- -- _|_)----|-----()----------- ----------()------------x-----
      14, Av. Pr. Franklin Roosevelt, 94320 Thiais, France Phone at CCMIX +33-1-57 42 91 09
    • Mar 26 2006 | 11:57 am
      Yes. I wouldn't worry too much about the symbol table.
      jb