Comments on: Conversions to string!

Carl Sassenrath, CTO
REBOL Technologies
27-Jun-2007 15:58 GMT

Article #0092
Main page || Index || Prior Article [0091] || Next Article [0093] || 17 Comments || Send feedback

REBOL has fairly complex rules for conversions to string. For example, it assumes that an issue, #abc should format without the # but money, $1.23 should always display the $.

It does not seem consistent. The reason: it was optimized for usability in the common cases. But, in R3, it may be time to change the rules.

Perhaps the question can be reduced to simply this: do we want to-string! to not add the datatype formatting?

As a clear example:

>> to string! 1
== "1"
>> to string! $1
== "$1.00"

Should we change that?

>> to string! $1
== "1"

What we need is to create a table of conversions and examine each one to decide what is best. [I could use some help on that, because my time is so restricted with R3 coding.]

Keep in mind that these converters are available:

 to-stringlow level conversion to a string
 formhigh level conversion to string
 formatconversion with specification (new in R3, but more to do)
 moldconversion to REBOL source format



27-Jun-2007 18:48:46
Conversions with a mask are widely used in many languages. I don't know the format fuction but I hope it will works like that:

>>format now "DD/MM/YY"
== "28/06/07"
>>format mydecimal "00000.00"
== "00123.45"
>> format %/home/joe/hello.txt "P : F"
== "/home/joe/ : hello.txt"
>> format "(D) P : F (Q)"
== "( ) /products/ : r3.html (details=2)"

In fact a general formating function that accepts different mask syntaxes following the datatype of the main argument.

Ged Byrne
27-Jun-2007 21:29:58
It would be nice if there was a simple way to convert currency to a string using the localised symbol (eg £)
28-Jun-2007 2:43:47

this blog is based upon my request to Carl to comment the issue. Well, what I wanted was to have reversible conversions, so that:

to-string to-money "1"

... gives us back =="1" string, istead of =="$1.00" one. But I may also stand corrected by Carl's claim, that simply what we have here is conversion functions chained. So in above example to-string converts money value, not an integer value, so maybe result of "$1.00" is correct.

However - I have to think about how usefull is that? Imagine following case:

to-pay: $1
print ["You are supposed to pay" to-pay "$."]
You are supposed to pay $1.00 $.

Now tell me - how usefull is to have money datatype here, if it stands in my way? How should I get above to be usefull? Convert 'to-pay to integer first? Also - print in above case doint automatic space insertion may not be helpfull in all cases, especially if you can't influence that.

I know the topic is difficult, because if we left-out datatype symbol, then loading might be difficult:

load "$1.00" will give us money type.

But - you can try yourself with various datatypes - it varries from type to type:

>> to-string 1
== "1"
>> to-string 1.00
== "1.0"
>> to-string $1
== "$1.00"
>> to-string #1
== "1"
>> to-string #{11}
== "^Q"
>> to-string %1
== "1"

Here's one catch from Chris, although using form, rejoin:
>> form #p
== "p"
>> form <p>
== "<p>"
>> rejoin [<p> "Paragraph" </p>]
== <pParagraph</p>>

My conclusion is - make things work in consistend = predictable way! If not, users will have to use trial and error aproach in console, to first check the result, then to use it. And that is not helpful aproach!

I know Carl planned formatting dialect for quite long time. Maybe now is the time to make things more usefull.

1) print block! automatically adds spaces to elements - I want to be able to influence that.
2) datatypes conversion are inconsistent. Find me a rule for that, which I can remember, or let's change it!
3) to-string 0.01 == "1E-2" is not usefull too. How many times we saw users struggling with that?
4) add padding function and stop making excuses, that it is easy to build one, because new users will ask for that anyway :-)

Simply - make some simple things more usefull ...


28-Jun-2007 8:08:35
Could there be a refinement like /keep to keep the datatype marker so we could have e.g.
>> m: $4
== $4.00
>> to-string m
== "4.00"
>> to-string/keep m
== "$4.00"
>> i: #123-abc
== #123-abc
>> to-string i
== "123-abc"
>> to-string/keep i
== "#123-abc"
28-Jun-2007 8:10:08
Please change behavior of 'print, which prints spaces between elements, when block is printed. That can't be easily avoided:

dot: "." print ["This is sentence" dot "And another one" dot]
==This is sentence . And another one .

I want to do it myself:

dot: "." print ["This is sentence" dot " And another one" dot]
dot: "." space: " " print ["This is sentence" dot space "And another one" dot]
==This is sentence. And another one.

28-Jun-2007 10:32:04
I also noticed this "strange" behavior in actual Rebol:

>> {salut
{ ca va?}
== "salut^/ca va?"
>> {saluuuuuuuuuuuuuuuuuuuuuuuuuut
{ ca vaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?}
== {saluuuuuuuuuuuuuuuuuuuuuuuuuut
ca vaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?}

While implementing RebelBB, I wanted to get the full post content "molded" into one single line with ^/ displayed to show a newline. Because I didn't understand why it is like this, I finally did a:

mold parse str "^/"
Doing so resulted into getting the one single line I was expecting... but I'm not proud of this solution :-(
28-Jun-2007 14:20:10
FWIW, here's what I use to convert numbers into my preferred "human readable" format.
to-commas: func [{Converts numbers to strings, adding thousands separators (commas).}
    num [number! money! string!] "Number (or string) to convert."
    slen [integer!] {Length of string to return, or 0 for no justification.} /local
    temp frac whole z y a len
    temp: to-string num
    frac: find temp "."
    either NONE? frac [
        whole: temp
        frac: ""
    ] [
        whole: copy/part temp (length? temp) - (length? frac)
    reverse whole
    z: length? whole
    y: 0
    a: ""
    foreach char whole [
        if char = #"$" [
            a: join a " "
            z: 0
        if ALL [(y = 3) (z > 0) (char <> #"-")] [
            a: join a ","
            y: 0
        a: join a char
        y: y + 1
        z: z - 1
    reverse a
    a: join a frac
    len: length? a
    if len < slen [
        a: insert/dup a " " (slen - len)
        a: head a
    return a

Some examples of its output:

> to-commas $12345.6789 20
== "         $ 12,345.68"
>> to-commas -12345.6789 20
== "        -12,345.6789"
>> to-commas -$12345.6789 20
== "        -$ 12,345.68"
>> to-commas -$12345.6789 2
== "-$ 12,345.68"
I'm sure this could be improved, because it doesn't provide for different currency symbols or thousands separators, but it does meet my needs here in the U.S.
Brian Hawley
28-Jun-2007 16:38:57
Please change behavior of 'print, which prints spaces between elements, when block is printed. That can't be easily avoided

Sure it can:

print rejoin [...]
Gregg Irwin
29-Jun-2007 8:53:01
Greg, I had a similar need, and ended up writing this func:
    single-line-mold: func [
        "Reformats a value to a single line."
        /all "Mold in serialized format"
        /local mold-all op
    ] [
        mold-all: func [value] [mold/all :value]
        op: either all [:mold-all] [:mold]
        if any-block? :val [val: new-line/all copy :val off]
        replace/all op :val "^/" "^^/"
I like the current behavior. If we change FORM to not format things like money, and PRINT uses FORM, suddenly we have to do detailed formatting rather than just using PRINT.
29-Jun-2007 11:05:09
Thanks Gregg, I'll update RebelBB using your function ;-)
Robert Shiplett
2-Jul-2007 13:30:34
REBOL [core]
join <p> "/" ;==
type? join <p> "/" ;== tag!
join [] 42
join {} "test"
join "" "test"
join <> #"p" ; error
join <> "p" ; error
join "<>" "p" ; oops, just kidding ...
comment { in the context of join, how could first param
<> be an op but not [] or {} ?}
Robert Shiplett
2-Jul-2007 13:41:39
To make things worse
join [1] [2]
join <p> <div>
join <> 1 2 (<> 1 2)
join (<>) "p"
Robet Shiplett
2-Jul-2007 13:51:28
; suggestion
join < > "p" ;== use space and insert element name
;result is <p>
join <p> <div> ; valid result is series of tags
Robert Shiplett
2-Jul-2007 13:58:19
; analogy for valid XML join
join #"p" #"q" ;== "pq"
; using a space is tough given
make tag! none
; an alternative change is to parse logical join <> 1 2 only when in parens as
join (<> 1 2)
Robert Shiplett
2-Jul-2007 14:11:47
; to open a Pandora's box, comma
join <,> "p" ;== <p>
Robert Shiplett
2-Jul-2007 14:30
; or drop join for tag as this is bad
join <div> {test="3"}
; and this is worse
join <elem/> {color="red"}
Artem Hlushko
5-Jul-2007 2:59:56
I propose to redesign a money datatype and make it to be parametrized with currency and fraction.
>> a: $10.00
== $10.00
>> b: £20.00
>> a + b
Error: money type currency mismatch
>> c: USD30.00
== USD30.00
>> a + c 
Error: money type currency mismatch
>> d: QAZ100.000
== QAZ100.000
With this datatype we can go further and do this:
>> e: GOOG1000
== GOOG1000
>> f: MSFT2000
== MSFT2000

Post a Comment:

You can post a comment here. Keep it on-topic.


Blog id:



 Note: HTML tags allowed for: b i u li ol ul font span div a p br pre tt blockquote

This is a technical blog related to the above topic. We reserve the right to remove comments that are off-topic, irrelevant links, advertisements, spams, personal attacks, politics, religion, etc.

Updated 30-Mar-2017 - Edit - Copyright REBOL Technologies -