• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp5907
r3wp58701
total:64608

results window for this page: [start: 52401 end: 52500]

world-name: r3wp

Group: !REBOL3 ... [web-public]
Gregg:
16-Feb-2010
The two suggestions from Andreas:


1) "TRUE for values that are equal and of the same case and datatype." 

2) "Returns TRUE for EQUAL? values that are of the same case and 
datatype."

I'll add the following option:


Returns TRUE for values that are equal and of the same case and datatype.
 


Which is just Andreas's #1 with "Returns" at the head, to match the 
doc string for EQUAL? and others.  That makes it 73 chars total. 
I don't think that's a problem, but I also don't think it's neccessary 
in this case. It wouldn't hurt of course, but certain information 
may have to be elided from doc strings, and this piece of information 
for STRICT-EQUAL? is easy to deduce and understand IMO.
Gregg:
16-Feb-2010
Andreas, what about something like one of these:


- "Returns TRUE if the values are strictly equal and of the same 
datatype." 

- "Returns TRUE if the values are strictly equal and the same datatype." 

- "Returns TRUE if the values are strictly equal, including their 
datatype." 

- "Returns TRUE if the values are strictly equal, including datatype." 


We can argue that just adding the word "strictly" doesn't help, but 
then the help for EQUAL? isn't very helpful either. :-) My thinking 
here is that there are a number of things that may seem confusing 
about strict equality, and we can't address them all in the doc string. 
Case sensitivity is important, and if we want to single that out, 
I'm OK with it, but might there be other cases as well?

>> strict-equal? d1 d2
== true
>> d1
== 16-Feb-2010/13:25:30-7:00
>> d2
== 16-Feb-2010/14:25:30-6:00
>> equal? [a] [A]
== true
>> strict-equal? [a] [A]
== false
>> strict-equal? 'a 'A
== true 


R3 addresses those cases, but are there others? What about user defined 
types (not sure what the status or goal is on utype! values at this 
point)?
Andreas:
16-Feb-2010
But actually, I quite like "Returns TRUE if the values are strictly 
equal." This does not lead a user who reads only the docstring to 
wrong conclusions.
Sunanda:
16-Feb-2010
Request for help received via REBOL.org's feedback form. If you can 
help, please post here and I'll forward him the URL of the archive:

===============

Using Rebol 3.0 Alpha, 2.100.97.3.1, how can I save the value removed 
from a series when I use the remove function? See example 1 below; 
I would like to be able to save the value "red" in a variable.  Can 
a "parse" statement be used instead of the remove. How would it be 
coded?

See example 2 below. Should'nt the value be "red"

example 1
text: "redblueyellow"
== "redblueyellow"
remove/part text 3
==text: "blueyellow"

Example 2
saved-text: "redblueyellow"
== "redblueyellow"
difference saved-text text
== "d"

I tried this an hour later and got 
== "rd"
===============
Sunanda:
16-Feb-2010
Is there a useful DIFF-type function anywhere that extracts the substring 
differences between strings?
BrianH:
16-Feb-2010
Added a comment to that ticket, with a suggestion for doc strings 
that fit the limit:

- STRICT-EQUAL? "Returns TRUE if the values are equal and of the 
same datatype, case."

- STRICT-NOT-EQUAL? "Returns TRUE if the values are equal and of 
the same datatype, case."

Nice, consise, and 68 and 69 characters, respectively, no problem. 
You can even change "datatype, case" to "datatype & case".
BrianH:
16-Feb-2010
That was a typo above.
BrianH:
16-Feb-2010
Because != and <> need a function to redirect to.
BrianH:
16-Feb-2010
And you can use STRICT-NOT-EQUAL? as a function value if need be, 
but not NOT STRICT-EQUAL?.
Robert:
17-Feb-2010
Would it be possible to make R3 a Windows-Host-Script language?
BrianH:
17-Feb-2010
There might be a workaround for that with extensions, but I'd wait 
until we have the next host kit before making an ActiveScripting 
host, so we can use embedded extensions and the revamped command! 
type.
Robert:
17-Feb-2010
Ok. IMO we need callbacks as well. And a good documentation how this 
will be integrated into the event system.
Robert:
17-Feb-2010
Is there a way to get the literal of a function parameter? 

Example:
 "my-funct my-data" and "my-funct: funct [parameter]..."



Can I get 'my-data within my-funct?
BrianH:
17-Feb-2010
As for your first question, try a lit-word parameter like this: my-funct: 
funct ['parameter]...
BrianH:
17-Feb-2010
Unless you want no evaluation at all, not just for words, then use 
a get-word parameter. Yes, that's an awkward way to refer to it - 
it's already been reported.
Gregg:
18-Feb-2010
Brian, if "Returns TRUE if the values are equal and of the same datatype 
& case." is OK, but "Returns TRUE if the values are equal and of 
the same datatype and case." is not, that's where I think uor priorities 
are out of order. 


Maybe the first thing we should do is write a clear goal for doc 
strings. What is their main purpose and what constraints should be 
placed on them for each purpose (or maybe I just haven't seen the 
doc that does this)? For example, are they be limited for console 
output only when listed with other funcs, or also when used with 
HELP individually? Should ? be short help and ??? link to a detailed 
help page for funcs? If console group list is the constraining factor, 
can it truncate and ellipsize longer strings?
Robert:
18-Feb-2010
Is there a difference between an object! or context! Any rules wheren 
to use one or the other? I use contexts more likea "class"(data, 
functions) and objects mor like blocks.
Robert:
18-Feb-2010
Hmm... true. So CONTEXT seems to be just a short-cut.
Geomol:
18-Feb-2010
Your unblock returns a series of words. You need to have them in 
a series (a block). You can do these:

first reduce [words-of my-object]
or simple
words-of my-object

I can't see, an unblock would be possible.
Robert:
18-Feb-2010
word-of returns a block
Geomol:
18-Feb-2010
Remember every function and operator in REBOL returns exactly one 
return value. Some would argue, PRINT doesn't, but it returns a value 
of the unset! datatype. If you need to return many words, you have 
to put them in one return value, like a block.
Geomol:
18-Feb-2010
I see, what you want, but you can't do that in REBOL, because a function 
can't return more than one value.
Robert:
18-Feb-2010
Yep, used the JOIN as well. But thought it's a generic pattern.
Geomol:
18-Feb-2010
COMPOSE is in R3, and it's a way to get the desired result.
Geomol:
18-Feb-2010
You can also use a function like this:

flatten: func [block /local result] [
	result: clear []
	forall block [
		append result either block! = type? block/1 [
			to paren! block/1
		][
			block/1
		]
	]
	result
]

>> flatten [1 [a 2] 3]
== [1 a 2 3]


Can only flatten one level. If you have blocks within blocks within 
blocks, you need another loop or make it recursive.
Geomol:
18-Feb-2010
I don't see a techinal reason. It could be implemented, but will 
slow date recognision down a little bit. I've considered sort of 
the same for thousand separators, so these could be recognized:

1.200,00
1,200.00

But will slow scanner a little bit and make code more complex.
Geomol:
18-Feb-2010
Graham, about the date thing. It's also a potential problem, if you 
forget to set the system prefs back and then run some script. Your 
dates would suddently behave strangely.
Geomol:
18-Feb-2010
Let's say, you did change you date pref once. Then a month later 
you read some data with some dates. Now, what format would you guess, 
those dates were in?
Graham:
18-Feb-2010
slow down date recognition a little ... I don't think so.  It could 
be vectored on rebol start up.
Paul:
18-Feb-2010
;Here is my old one from R2 just quickly formatted for R3:

flatten: make function! [[

    {Returns a new block with desired blocks flattened or removed}
    blk [block!] "block to flatten"
     /fine "Flattens blocks to finest representation"
     /semi "Flattens to support 'select operations"
     /full "Flatten fully - ignored with other refinements"
     /local blk2
    ][
    blk2: copy []
    fl: func [b][
        either parse b [block!][
            b: first b
            fl b
        ][
            either semi [
                insert tail blk2 b
            ][
                either full [

                    foreach val b [either block? val [fl val][insert tail blk2 val]]
                ][
                    insert/only tail blk2 b
                ]
            ]
        ]
    ]

    if fine [full: none while [parse blk [block!]][blk: first blk]]
    foreach item blk [
        either block? item [fl item][insert tail blk2 item]
    ]    
    blk2
]]
Gabriele:
19-Feb-2010
graham, yes, but code is data as well. how can we make something 
like that apply to "data" only and not scripts? in the end, i think 
it's more a matter of needing "custom" parsing for your data, which 
could be made easier (eg. by having special built in parse rules 
for dates and so on)
Oldes:
19-Feb-2010
This is a very nice version Steeve. You should post it to the "favourite 
parse" blog. So we at least get back to it's topic.
Steeve:
19-Feb-2010
it's done since a while, but noone noticed it. :)
Ashley:
19-Feb-2010
A little something I put together to help R3 developers: http://www.dobeash.com/REBOL/r3-ref.html
Claude:
20-Feb-2010
'import do not 'do a module !!!!
Claude:
20-Feb-2010
when i but new_word into a file new_word.r and test_mod into test_mod.r 
and i try to import them
Claude:
20-Feb-2010
>> import %new_word.r
>> import %test_mod.r
** Script error: new_word word is not bound to a context
** Where: do applier make module do applier make catch if import
** Near: do body obj
Graham:
20-Feb-2010
Does r3 chat actually have a built in revision system?
Henrik:
20-Feb-2010
Graham, it has an approval system like devbase, but I don't know 
about a real revision system.
Paul:
20-Feb-2010
Just a small script:

#!/home/paulsite/dist/r3 -c
REBOL []
print [<HTML><BODY> now </BODY></HTML>]
print ""
Graham:
20-Feb-2010
I've created a git repository and stored all the protocol stuff there 
... http://github.com/gchiu/Rebol3
Graham:
20-Feb-2010
If anyone wants to collaborate and to add their stuff ... or add 
RT's stuff ... PM me and I'll add you as a collaborator
Graham:
20-Feb-2010
Note, a lot of the stuff is alpha quality ... but so is R3 :)
BrianH:
20-Feb-2010
Ladislav, objects don't have a 'self field in R3 - the 'self binding 
is a side-effect of the BIND function. You shouldn't be using IN 
object 'self in R2 either - use BIND?.
Pekr:
21-Feb-2010
hmm, why does not it work?

>> foreach word words-of system [print get in system word]
core
2.100.97.3.1
7-Feb-2010/4:31:57
** Script error: Windows word is not bound to a context
** Where: print foreach
** Near: print get in system word
Steeve:
21-Feb-2010
i meant, a fast way...
Gregg:
21-Feb-2010
What test code? Henrik and I both did some on R3-alpha, but Carl 
wanted a simple block format, and I don't know where any of that 
is.
Ladislav:
22-Feb-2010
objects don't have a 'self field in R3

 - interesting, I always thought, that if I hide something, it does 
 not cease to exist...
Paul:
22-Feb-2010
>> obj: context [a: does [probe self]]
== make object! [
    a: make function! [[][probe self]]
]

>> obj/a
make object! [
    a: make function! [[][probe self]]
]
== make object! [
    a: make function! [[][probe self]]
]
BrianH:
22-Feb-2010
In any case, the code that you have been using to demonstrate your 
complaint (with the exception of Paul's above) is an example of what 
we are trying to avoid people doing. Don't use IN object 'self, it's 
a bad idea. Use BIND?.
BrianH:
22-Feb-2010
So to discourage that behavior, 'self is hidden as-if with PROTECT/hide 
(effectively, not really), blocked from modification as-if with PROTECT 
(effectively, not really), not counted by LENGTH?, not unprotectable 
by UNPROTECT and only referenceable through BIND block! any-object!. 
It is unknown by anyone other than Carl whether the field actually 
exists in the object at all - I would guess that it does, because 
the alternative seems more complex and that's not his style. In any 
case, every reasonable effort has been made to discourage its use 
in any way except in code like Paul demonstrates above. R2's usage 
of the word was a security hole, and unnecessary once we got the 
BIND? function, both in R2 and R3.
BrianH:
22-Feb-2010
And was a security hole. And so is explicitly blocked.
Jerry:
22-Feb-2010
Last night, I dreamed that Carl announced in his R3 Blog that A98 
was released. The first thing I did in the morning was to make sure 
it's real. It's not. ... I need to see a shrink, seriously.
Pekr:
23-Feb-2010
Jerry ... we all wish for things to proceed faster. However, we have 
to wait a bit. Hopefully Carl is doing wildly in the HostKit/Extension 
area, so that guys can proceed with other areas, as GUI for example 
...
Graham:
23-Feb-2010
There's a real paucity of news at present.
Pekr:
23-Feb-2010
I am encountering a crash, dunno if easily traceable. I start R3, 
type-in "chat". Then I quit the chat by "q", then I type "demo" .... 
and R3 crashes ...
Graham:
24-Feb-2010
Pekr, putting a trace before demo and it doesn't crash.  Very odd.
Graham:
24-Feb-2010
Still tracing ... seems to be doing a lot with nothing happening. 
 I would have thought the whole GUI would be in a wait
PeterWood:
24-Feb-2010
I tried the chat then demo trick under linux and Rebol crashed with 
a segmentation fault. Normally, the demo gives a script error. I 
also tried on Mac OS X but that was okay - the demo gave a script 
error.
Graham:
24-Feb-2010
when I do a 'n, but show when I type the number in...
BrianH:
25-Feb-2010
6993 wasn't a message, it was a move of 2 of Paul's messages to the 
right heading. Not every number is a message - everything gets a 
number, including headers, moves, deletes, file operations, etc.
BrianH:
27-Feb-2010
Wow, I never realized what overhead TRY/except has, but that overhead 
seems to be fixed. As long as you can safely run until an error without 
having to roll back changes, that could be a good strategy. Sticking 
to the R3 safety model (generating errors before it matters with 
functions like ASSERT) you can make code that runs faster in the 
default case, and safely always.
Steeve:
28-Feb-2010
But we can't check anymore for the type of the last happend error 
with try/except.

>> try/except [1 / 0][error? probe system/state/last-error]
none
== false.

it's a problem, we can't have an accurate process error handler.

I think it's a missing feature (or the error is somewhere else in 
the system object).
BrianH:
28-Feb-2010
As parse rules go, it wouldn't be difficult. Try this:
>> hex: charset [#"0" - #"9" #"a" - #"f" #"A" - #"F"]
== make bitset! #{000000000000FFC07E0000007E}

>> parse a: "paul%40tretbase.com" [any [to "%" [b: skip copy x 2 
hex (b: change/part b to-char first debase/base x 16 3) :b | skip]]] 
a
== "[paul-:-tretbase-:-com]"

Now that is a modifying method, but it should be easy to adapt that 
to a copying method.
BrianH:
28-Feb-2010
With the full change rule it would be this:

>> parse a: "paul%40tretbase.com" [any [to "%" [change [skip copy 
x 2 hex] (to-char first debase/base x 16) | skip]]] a
Paul:
28-Feb-2010
Is there a new method to send email in R3?
Paul:
28-Feb-2010
Ok doesn't look like it.  Looks like we have to build a new send 
function for R3.
Graham:
28-Feb-2010
I use 'use a lot attached usually to GUI buttons.   Wonder if it's 
worthwhile to have a version like funct that automatically makes 
all set words local so that we don't have to declare them
sqlab:
1-Mar-2010
Is there a list of  words reserved for parse, as

>> parse "a b" [ copy limit to " " ]

** Script error: PARSE - command cannot be used as variable: limit
** Where: parse
** Near: parse "a b" [copy limit to " "]

>> parse "a b" [ limit ]

** Internal error: reserved for future use (or not yet implemented)
** Where: parse
** Near: parse "a b" [limit]
BrianH:
1-Mar-2010
Sqlab, 'limit is reserved for a planned parse ooperation that Carl 
doesn't know how to implement yet.
Paul:
2-Mar-2010
attempt needs to as lean as possible since it could be within loops 
being called a lot.  So I would propose that another solution might 
be to add another function.  Like to DEFUSE the block being passed 
to ATTEMPT.  So you can do something like ATTEMPT DEFUSE [some block] 
     The defuse function would return/pass the defused block to attempt 
to be evaluated.
Sunanda:
2-Mar-2010
I've given it some more thought and think I have combined two issues 
that could better be dealt with separately:

1. TRY and ATTEMPT as ways of protecting my code:

Generally, the current behavior is surprising but in most cases acceptable.

It is rare that something as stupid as attempt [exit] would make 
it to production status. So, in many cases  no problem. [perhaps 
an odd problem if my app is generating code (eg a genetic algorithm). 
But knowing the problem, that could be guarded against]. 

2. TRY and ATTEMPT for protecting arbitrary code

As Gregg suggests, that needs a careful, systems-level design to 
get right and to make robust. REBOL3 offers some help (SECURITY policies, 
ATTEMPT, TRY, CALL) but isolating code into a safe sandbox, and recovering 
from any possible error/lapse/attack is not something the language 
alone can provide.


Still, making TRY and ATTEMPT fully predictable [succeed or return 
an ERROR] would be most welcome!
BrianH:
3-Mar-2010
The trick, Sunanda, is that the code that you want ATTEMPT to catch 
isn't actually erroneous. EXIT itself never generates an error - 
it basically is like a fancy goto that has to be caught by a handler. 
However, the handler can trigger an error (the one that you see) 
if the goto supposedly isn't handled; actually, all such goto functions 
are always handled and never cause an error directly, it is the handlers 
that cause the error.


The problem is really one of perception: Code that you think is erroneous 
(but isn't) is not triggering errors (and shouldn't), and the code 
that is triggering the error is not actually inside the code block 
that you are passing to TRY or ATTEMPT. Perceptual problems are tricky 
- either you have to change your perceptions, or rewrite the basic 
semantics of the language. Which is easier in this case?
Sunanda:
3-Mar-2010
But 
  exit
_is_ an error on its own.

It is hard to see why ATTEMPTing an error "is never an error on its 
own", especially as trying it by itself in a console does create 
an error.  
  exit  ;; REBOL says is an error
  attempt [exit]  ;; Brian and I disagree if this is an error

it creates a horribly inconsistent mental model.

You could create a trivia/gotcha quiz arond this. Which of these 
stop with an error?
  attempt [throw]
  attempt [throw 0]
  attempt [throw/break]
  attempt [throw/break 0]
  attempt [throw/name]
  attempt [throw/name 0 0]
  attempt [throw/name 0 'x]
BrianH:
3-Mar-2010
Wait, the THROW/break ones always generate an error. THROW doesn't 
have a /break refinement.
BrianH:
3-Mar-2010
THROW 0 is always correct in and of itself. It's not THROW's fault 
you called it outside of a CATCH, it's yours.
BrianH:
3-Mar-2010
No, but it works the same, just faster. Almost all functions that 
had a [throw] attribute in R2 (or needed one, like ATTEMPT) were 
converted to natives in R3. We're still waiting for the new equivalent 
of the [throw] attribute to be added to R3 - right now USE, OBJECT 
and CONTEXT are the only built-in functions that still need it, afaik.
BrianH:
3-Mar-2010
Note that the ticket was marked as a problem, not dismissed (yet). 
The problem was explained in the comments, and more thoroughly now 
in my more recent reply there.
Sunanda:
3-Mar-2010
I think I can answer my own question about executing arbitary code.

Just tried the ancient error? try technique:

   error? try [break]  ;; I'm happy
   attempt [break]   ;;  still think this is a bug!
BrianH:
3-Mar-2010
There's even a CureCode ticket for it, which you referred to in your 
comment.
Henrik:
3-Mar-2010
From my perspective, attempt [break] is working correctly. ATTEMPT 
has nothing to do with the BREAK, it simply passes it to the outer 
context (if you can say that) and then the BREAK doesn't hold up, 
because it's not inside a function. Seems simple to me.
Henrik:
3-Mar-2010
>> a: does [attempt [exit] 1]
>> a
>>

Looks fine and dandy.
BrianH:
3-Mar-2010
The question (only for Carl) is whether task-local runtime contextual 
information can be made available to BREAK, EXIT, RETURN and THROW 
to let them know that they are going to be handled by the console, 
which would let them throw the error that the console should be throwing, 
on behalf of the console. Basically, letting them be more polite. 
The problem is that it is *really* likely (only Carl would know) 
that this would slow down all function! and closure! calls, all loops, 
and every call to DO (even indirectly, as in IF) by quite a bit. 
It could make R3 a lot slower (maybe several times slower).
BrianH:
3-Mar-2010
ATTEMPT and TRY push a handler for exceptions with codes over 100 
on the task-local handler stack. Those exceptions are generated by 
DO MAKE error! (or code called by natives with the same effect).
Paul:
3-Mar-2010
Brian, I agree with you.  I think if we make Try or Attempt handle 
these other exceptions then we are going to slow things down.  Again, 
we have  a way to handle this now.  No need to pursue the problem 
at this point.
Andreas:
3-Mar-2010
I think it uncovered not a bug in the implementation, but provokes 
a discussion on the language semantics.
Sunanda:
3-Mar-2010
Thanks for the repeated attempts to explain, Brian!

For me, the work around is:
    error? try [....]
That seems to work in all cases I have tried.


[Ironically, 99% of all the REBOL code I have ever written uses ERROR? 
TRY --  ATTEMPT did not exist when I started REBOL, and my fingers 
have learned to type the idiom. It's only with R3 that I'ved tried 
to update my error handling.....Seems I should stick with my older 
ways for a while...:)]
Andreas:
3-Mar-2010
That means, an erroneous use of e.g. BREAK would simply result in 
a "has no value" error, just as the use of any other unset word. 
And this error would of course be nicely caught by ATTEMPT.
Sunanda:
3-Mar-2010
The crux of the issue for me is this:
  attempt [badcode] print true
I (naively perhaps) suggest that this should always either:
-- close the console (if badcode has a QUIT); or
-- halt (if  badcode has a HALT; or
-- print TRUE in all other cases.


Brian argues that there are internal engineering reasons for a fourth 
possibility:
-- ATTEMPT returns an error message
Andreas:
3-Mar-2010
Easy
 from a language design perspective, that is.
BrianH:
3-Mar-2010
Sunanda, that error? try [....] code you keep mentioning doesn't 
work in all cases you mention. The problem is this:
>> error? break
== true

This is an error (bug#771 and bug#862): It should not return true, 
it should break and then later on trigger an error for an unhandled 
break. To illustrate why:
>> loop 1 [error? break 'buggy]
== buggy

That should have returned unset, not continued. The BREAK is supposed 
to halt execution and resume it somewhere else, either after the 
enclosing loop or at the top level. The same error is affecting your 
error? try [....] code, which is not behaving correctly. 


Your problem, Sunanda, is that you are thinking that ATTEMPT is not 
catching bad code (bugs) that it is supposed to catch - this is not 
strictly true. ATTEMPT isn't supposed to catch bugs, it is supposed 
to catch triggered errors. And a lot of logic bugs don't trigger 
errors, because the code itself is technically correct (what REBOL 
can check for), but not in accordance with the programmer's intentions 
(which REBOL can't know).


Now in this case the logic bug is that you have forgotten that the 
purpose of the BREAK, CONTINUE, THROW, EXIT and RETURN functions 
is escape from the normal flow of the code ("structured" gotos, aka 
non-local returns, exceptions, ...) - you remembered this about HALT 
and QUIT - and didn't realize that the error you are trying to catch 
with ATTEMPT is not in the code that you have wrapped in the ATTEMPT: 
It is not bad code. The error is triggered by the code on the other 
end, the handler, which is not wrapped in the ATTEMPT at all.

So you need to realize that this code is technically correct:
>> attempt [break]
** Throw error: no loop to break
but doesn't do what you thought it should.

And this code is absolutely incorrect:
>> error? try [break]
== true

but doesn't trigger an error because of a weird design quirk in R3 
that is arguably a bug, but not necessarily fixable (see bug#771 
and bug#862).
BrianH:
3-Mar-2010
Created a ticket (bug#1509) to explain the real problem with these 
functions.
Paul:
3-Mar-2010
do we really want this behavior:

>> obj: construct [a: b: c: 1]
== make object! [
    a: 1
    b: 1
    c: 1
]
Paul:
3-Mar-2010
I think we need a way to pass that block so that 'a and 'b can evaluate 
to none
Paul:
3-Mar-2010
It is clear why it setting a and b to 1 but we need to have something 
a bit safer.
Paul:
3-Mar-2010
>> a: construct/only [c: d: 1]
== make object! [
    c: 1
    d: 1
]
Paul:
3-Mar-2010
I understand that but we need a feature in which they are NOT.
BrianH:
3-Mar-2010
>> construct/only [a: b:]
== make object! [
    a: none
    b: none
]
Paul:
3-Mar-2010
that is still a chained assignment
BrianH:
3-Mar-2010
But that's not a problem.
52401 / 6460812345...523524[525] 526527...643644645646647