caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] String.(r)index_from
@ 2013-08-12 10:55 Florent Monnier
  2013-08-12 12:58 ` Gerd Stolpmann
  0 siblings, 1 reply; 6+ messages in thread
From: Florent Monnier @ 2013-08-12 10:55 UTC (permalink / raw)
  To: caml-list

Hi,

Is this the expected behavior?

# let s = "012" ;;
val s : string = "012"

# String.index_from s 1 '1' ;;
- : int = 1
# String.index_from s 2 '2' ;;
- : int = 2
# String.index_from s 3 '3' ;;
Exception: Not_found.
# String.index_from s 4 '4' ;;
Exception: Invalid_argument "String.index_from".

(* ====================== *)

# String.rindex_from s 1 '1' ;;
- : int = 1
# String.rindex_from s 0 '0' ;;
- : int = 0
# String.rindex_from s (-1) '#' ;;
Exception: Not_found.
# String.rindex_from s (-2) '#' ;;
Exception: Invalid_argument "String.rindex_from".

(* ====================== *)

# String.contains_from s 2 '2' ;;
- : bool = true
# String.contains_from s 3 '2' ;;
- : bool = false
# String.contains_from s 4 '2' ;;
Exception: Invalid_argument "String.contains_from".

(* ====================== *)

If yes, please just ignore this email.

If no, here is a patch for the file "string.ml":
http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/trunk/stdlib/string.ml?view=markup&pathrev=13748

### return exception Invalid_argument instead of false or Not_found
### when the index is out of bounds.
--- stdlib/string.ml.orig	2013-08-12 12:42:17.443013642 +0200
+++ stdlib/string.ml	2013-08-12 12:43:24.973014347 +0200
@@ -176,7 +176,7 @@

 let index_from s i c =
   let l = length s in
-  if i < 0 || i > l then invalid_arg "String.index_from" else
+  if i < 0 || i >= l then invalid_arg "String.index_from" else
   index_rec s l i c;;

 let rec rindex_rec s i c =
@@ -186,12 +186,12 @@
 let rindex s c = rindex_rec s (length s - 1) c;;

 let rindex_from s i c =
-  if i < -1 || i >= length s then invalid_arg "String.rindex_from" else
+  if i < 0 || i >= length s then invalid_arg "String.rindex_from" else
   rindex_rec s i c;;

 let contains_from s i c =
   let l = length s in
-  if i < 0 || i > l then invalid_arg "String.contains_from" else
+  if i < 0 || i >= l then invalid_arg "String.contains_from" else
   try ignore (index_rec s l i c); true with Not_found -> false;;

 let contains s c = contains_from s 0 c;;
(* ====================== *)


The behavior of these functions is then to raise
an Invalid_argument exception if the index is out of bounds:

# let s = "012" ;;
val s : string = "012"

# String.index_from s 3 '3' ;;
Exception: Invalid_argument "String.index_from".

# String.rindex_from s (-1) '#' ;;
Exception: Invalid_argument "String.rindex_from".

# String.contains_from s 3 '2' ;;
Exception: Invalid_argument "String.contains_from".

(* ====================== *)

-- 
Best regards
florent

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] String.(r)index_from
  2013-08-12 10:55 [Caml-list] String.(r)index_from Florent Monnier
@ 2013-08-12 12:58 ` Gerd Stolpmann
  2013-08-19 18:19   ` Damien Doligez
  2013-08-20 15:53   ` Florent Monnier
  0 siblings, 2 replies; 6+ messages in thread
From: Gerd Stolpmann @ 2013-08-12 12:58 UTC (permalink / raw)
  To: Florent Monnier; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 3544 bytes --]

IMHO, this is the right behavior. When walking over strings, it is often
practical to consider the position after the last character as legal
position. So far I see, this is consistent in the String module, e.g.
you can also do String.sub "abc" 3 0.

It's a bit like considering 0 as natural number.

Gerd

Am Montag, den 12.08.2013, 12:55 +0200 schrieb Florent Monnier:
> Hi,
> 
> Is this the expected behavior?
> 
> # let s = "012" ;;
> val s : string = "012"
> 
> # String.index_from s 1 '1' ;;
> - : int = 1
> # String.index_from s 2 '2' ;;
> - : int = 2
> # String.index_from s 3 '3' ;;
> Exception: Not_found.
> # String.index_from s 4 '4' ;;
> Exception: Invalid_argument "String.index_from".
> 
> (* ====================== *)
> 
> # String.rindex_from s 1 '1' ;;
> - : int = 1
> # String.rindex_from s 0 '0' ;;
> - : int = 0
> # String.rindex_from s (-1) '#' ;;
> Exception: Not_found.
> # String.rindex_from s (-2) '#' ;;
> Exception: Invalid_argument "String.rindex_from".
> 
> (* ====================== *)
> 
> # String.contains_from s 2 '2' ;;
> - : bool = true
> # String.contains_from s 3 '2' ;;
> - : bool = false
> # String.contains_from s 4 '2' ;;
> Exception: Invalid_argument "String.contains_from".
> 
> (* ====================== *)
> 
> If yes, please just ignore this email.
> 
> If no, here is a patch for the file "string.ml":
> http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/trunk/stdlib/string.ml?view=markup&pathrev=13748
> 
> ### return exception Invalid_argument instead of false or Not_found
> ### when the index is out of bounds.
> --- stdlib/string.ml.orig	2013-08-12 12:42:17.443013642 +0200
> +++ stdlib/string.ml	2013-08-12 12:43:24.973014347 +0200
> @@ -176,7 +176,7 @@
> 
>  let index_from s i c =
>    let l = length s in
> -  if i < 0 || i > l then invalid_arg "String.index_from" else
> +  if i < 0 || i >= l then invalid_arg "String.index_from" else
>    index_rec s l i c;;
> 
>  let rec rindex_rec s i c =
> @@ -186,12 +186,12 @@
>  let rindex s c = rindex_rec s (length s - 1) c;;
> 
>  let rindex_from s i c =
> -  if i < -1 || i >= length s then invalid_arg "String.rindex_from" else
> +  if i < 0 || i >= length s then invalid_arg "String.rindex_from" else
>    rindex_rec s i c;;
> 
>  let contains_from s i c =
>    let l = length s in
> -  if i < 0 || i > l then invalid_arg "String.contains_from" else
> +  if i < 0 || i >= l then invalid_arg "String.contains_from" else
>    try ignore (index_rec s l i c); true with Not_found -> false;;
> 
>  let contains s c = contains_from s 0 c;;
> (* ====================== *)
> 
> 
> The behavior of these functions is then to raise
> an Invalid_argument exception if the index is out of bounds:
> 
> # let s = "012" ;;
> val s : string = "012"
> 
> # String.index_from s 3 '3' ;;
> Exception: Invalid_argument "String.index_from".
> 
> # String.rindex_from s (-1) '#' ;;
> Exception: Invalid_argument "String.rindex_from".
> 
> # String.contains_from s 3 '2' ;;
> Exception: Invalid_argument "String.contains_from".
> 
> (* ====================== *)
> 
> -- 
> Best regards
> florent
> 

-- 
------------------------------------------------------------
Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
My OCaml site:          http://www.camlcity.org
Contact details:        http://www.camlcity.org/contact.html
Company homepage:       http://www.gerd-stolpmann.de
------------------------------------------------------------


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] String.(r)index_from
  2013-08-12 12:58 ` Gerd Stolpmann
@ 2013-08-19 18:19   ` Damien Doligez
  2013-08-20 15:23     ` Florent Monnier
  2013-08-20 15:53   ` Florent Monnier
  1 sibling, 1 reply; 6+ messages in thread
From: Damien Doligez @ 2013-08-19 18:19 UTC (permalink / raw)
  To: caml users

Hi,

Indeed, it was carefully designed this way. When you're doing
index_from s 3 '3', you're looking for the character 3 in the empty
string.

-- Damien



On 2013-08-12, at 14:58, Gerd Stolpmann wrote:

> IMHO, this is the right behavior. When walking over strings, it is often
> practical to consider the position after the last character as legal
> position. So far I see, this is consistent in the String module, e.g.
> you can also do String.sub "abc" 3 0.
> 
> It's a bit like considering 0 as natural number.
> 
> Gerd
> 
> Am Montag, den 12.08.2013, 12:55 +0200 schrieb Florent Monnier:
>> Hi,
>> 
>> Is this the expected behavior?
>> 
>> # let s = "012" ;;
>> val s : string = "012"
>> 
>> # String.index_from s 1 '1' ;;
>> - : int = 1
>> # String.index_from s 2 '2' ;;
>> - : int = 2
>> # String.index_from s 3 '3' ;;
>> Exception: Not_found.
>> # String.index_from s 4 '4' ;;
>> Exception: Invalid_argument "String.index_from".
>> 
>> (* ====================== *)
>> 
>> # String.rindex_from s 1 '1' ;;
>> - : int = 1
>> # String.rindex_from s 0 '0' ;;
>> - : int = 0
>> # String.rindex_from s (-1) '#' ;;
>> Exception: Not_found.
>> # String.rindex_from s (-2) '#' ;;
>> Exception: Invalid_argument "String.rindex_from".
>> 
>> (* ====================== *)
>> 
>> # String.contains_from s 2 '2' ;;
>> - : bool = true
>> # String.contains_from s 3 '2' ;;
>> - : bool = false
>> # String.contains_from s 4 '2' ;;
>> Exception: Invalid_argument "String.contains_from".
>> 
>> (* ====================== *)
>> 
>> If yes, please just ignore this email.
>> 
>> If no, here is a patch for the file "string.ml":
>> http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/trunk/stdlib/string.ml?view=markup&pathrev=13748
>> 
>> ### return exception Invalid_argument instead of false or Not_found
>> ### when the index is out of bounds.
>> --- stdlib/string.ml.orig	2013-08-12 12:42:17.443013642 +0200
>> +++ stdlib/string.ml	2013-08-12 12:43:24.973014347 +0200
>> @@ -176,7 +176,7 @@
>> 
>> let index_from s i c =
>>   let l = length s in
>> -  if i < 0 || i > l then invalid_arg "String.index_from" else
>> +  if i < 0 || i >= l then invalid_arg "String.index_from" else
>>   index_rec s l i c;;
>> 
>> let rec rindex_rec s i c =
>> @@ -186,12 +186,12 @@
>> let rindex s c = rindex_rec s (length s - 1) c;;
>> 
>> let rindex_from s i c =
>> -  if i < -1 || i >= length s then invalid_arg "String.rindex_from" else
>> +  if i < 0 || i >= length s then invalid_arg "String.rindex_from" else
>>   rindex_rec s i c;;
>> 
>> let contains_from s i c =
>>   let l = length s in
>> -  if i < 0 || i > l then invalid_arg "String.contains_from" else
>> +  if i < 0 || i >= l then invalid_arg "String.contains_from" else
>>   try ignore (index_rec s l i c); true with Not_found -> false;;
>> 
>> let contains s c = contains_from s 0 c;;
>> (* ====================== *)
>> 
>> 
>> The behavior of these functions is then to raise
>> an Invalid_argument exception if the index is out of bounds:
>> 
>> # let s = "012" ;;
>> val s : string = "012"
>> 
>> # String.index_from s 3 '3' ;;
>> Exception: Invalid_argument "String.index_from".
>> 
>> # String.rindex_from s (-1) '#' ;;
>> Exception: Invalid_argument "String.rindex_from".
>> 
>> # String.contains_from s 3 '2' ;;
>> Exception: Invalid_argument "String.contains_from".
>> 
>> (* ====================== *)
>> 
>> -- 
>> Best regards
>> florent
>> 
> 
> -- 
> ------------------------------------------------------------
> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
> My OCaml site:          http://www.camlcity.org
> Contact details:        http://www.camlcity.org/contact.html
> Company homepage:       http://www.gerd-stolpmann.de
> ------------------------------------------------------------
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] String.(r)index_from
  2013-08-19 18:19   ` Damien Doligez
@ 2013-08-20 15:23     ` Florent Monnier
  0 siblings, 0 replies; 6+ messages in thread
From: Florent Monnier @ 2013-08-20 15:23 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml users

2013/08/19, Damien Doligez wrote:
> Hi,
Hi,

> Indeed, it was carefully designed this way. When you're doing
> index_from s 3 '3', you're looking for the character 3 in the empty
> string.

OK, I do understand now that the offsets don't really point to cells
but on the interval (or separations) between cells. So 0 points to the
left part of the first char, and the offset = length points to the
right part of the last char, but I still don't catch the logic for the
functions that operates from right to left:

# let s = "012";;
val s : string = "012"

# String.rindex_from s 0 '0' ;;
- : int = 0

# String.rindex_from s (-1) '0' ;;
Exception: Not_found.

# String.rcontains_from s 0 '0' ;;
- : bool = true

# String.rcontains_from s (-1) '0' ;;
Exception: Invalid_argument "String.rcontains_from".

For the functions that operates from left to right, the ranges are
then consistently always the same, but not for the functions that
operates from right to left.

-- 
Regards

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] String.(r)index_from
  2013-08-12 12:58 ` Gerd Stolpmann
  2013-08-19 18:19   ` Damien Doligez
@ 2013-08-20 15:53   ` Florent Monnier
  2013-08-21  0:42     ` Francois Berenger
  1 sibling, 1 reply; 6+ messages in thread
From: Florent Monnier @ 2013-08-20 15:53 UTC (permalink / raw)
  To: Caml List

2013/08/12, Gerd Stolpmann wrote:
> IMHO, this is the right behavior. When walking over strings, it is often
> practical to consider the position after the last character as legal
> position. So far I see, this is consistent in the String module, e.g.
> you can also do String.sub "abc" 3 0.
>
> It's a bit like considering 0 as natural number.

Hi Gerd,

Well I can understand that there is some kind of logic there, even if
the logic is different than the one that I expected at the beginning.
But it doesn't seem to be very consistent with the functions that
perform searches from right to left:

# let s = "012";;
val s : string = "012"

# let n = String.length s ;;
val n : int = 3

# String.sub s n 0 ;;
- : string = ""

(* OK, so why is n valid for String.sub, but not for these below? *)

# String.rcontains_from s (n-1) '2' ;;
- : bool = true

# String.rcontains_from s n '2' ;;
Exception: Invalid_argument "String.rcontains_from".

# String.rindex_from s (n-1) '2' ;;
- : int = 2

# String.rindex_from s n '2' ;;
Exception: Invalid_argument "String.rindex_from".


-- 
Regards

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] String.(r)index_from
  2013-08-20 15:53   ` Florent Monnier
@ 2013-08-21  0:42     ` Francois Berenger
  0 siblings, 0 replies; 6+ messages in thread
From: Francois Berenger @ 2013-08-21  0:42 UTC (permalink / raw)
  To: caml-list

Hi Florent,

If you find yourself doing non trivial things with
the String module, maybe it means you should use another
module which works at a higher level.
Str for example, or some other module from extended
versions of the stdlib.

Regards,
F.

On 8/21/13 12:53 AM, Florent Monnier wrote:
> 2013/08/12, Gerd Stolpmann wrote:
>> IMHO, this is the right behavior. When walking over strings, it is often
>> practical to consider the position after the last character as legal
>> position. So far I see, this is consistent in the String module, e.g.
>> you can also do String.sub "abc" 3 0.
>>
>> It's a bit like considering 0 as natural number.
>
> Hi Gerd,
>
> Well I can understand that there is some kind of logic there, even if
> the logic is different than the one that I expected at the beginning.
> But it doesn't seem to be very consistent with the functions that
> perform searches from right to left:
>
> # let s = "012";;
> val s : string = "012"
>
> # let n = String.length s ;;
> val n : int = 3
>
> # String.sub s n 0 ;;
> - : string = ""
>
> (* OK, so why is n valid for String.sub, but not for these below? *)
>
> # String.rcontains_from s (n-1) '2' ;;
> - : bool = true
>
> # String.rcontains_from s n '2' ;;
> Exception: Invalid_argument "String.rcontains_from".
>
> # String.rindex_from s (n-1) '2' ;;
> - : int = 2
>
> # String.rindex_from s n '2' ;;
> Exception: Invalid_argument "String.rindex_from".
>
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-08-21  0:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-12 10:55 [Caml-list] String.(r)index_from Florent Monnier
2013-08-12 12:58 ` Gerd Stolpmann
2013-08-19 18:19   ` Damien Doligez
2013-08-20 15:23     ` Florent Monnier
2013-08-20 15:53   ` Florent Monnier
2013-08-21  0:42     ` Francois Berenger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).