Simplify the definition and use of custom index operators#69
Simplify the definition and use of custom index operators#69Octachron wants to merge 4 commits intoocaml:trunkfrom
Conversation
|
I like the change, but I'm less convinced by the |
|
That sounds quite an interesting extension! Seems that can encode python-like dictionaries using your |
|
Awesome idea! I look forward to that being implemented in the standard distribution. |
|
Would it be possible to add custom operators ? Following the ocaml convention, something like "start with |
|
A previous related proposal (for monadic operators rather than index-access operators) was shot down as too complex after we started arguing about which custom operators were reasonable. If I were you, I would first concentrate on a minimum viable proposal, and revisit the "custom operators" idea a few versions later. |
|
@gasche You're probably right, I don't want to start this kind of discussion. |
|
@gasche I agree that the @Drup The problem with adding custom operators is also that it becomes more difficult |
|
@Octachron I believe you could avoid the unsafe variants by adding a module and exposes them as externals in the interface. By exposing the externals in the interface, they are guaranteed to be inlined when used. This means that the behaviour of the EDIT: Actually, I suppose you are defining |
stdlib/pervasives.mli
Outdated
There was a problem hiding this comment.
The desugared examples here and and in the following ocamldoc comments should probably be wrapped in [] so that it is properly marked up by ocamldoc:
... is desugared to [( .() ) a index] if the ....
|
@lpw25 Thank you for your suggestion. Using new compiler primitives for the index operators This new version removes the |
|
In fact this can break some code of users relying on the orignal 'feature'. module S = struct
module Bigarray = struct
module Array1 = struct
let get x y = Hashtbl.find x y
let set x y z = Hashtbl.add x y z
end
end
end
let t = Hashtbl.create 1
let _ = S.(t.{1} <- 'x'; t.{1}) |
|
True. This change would break any code relying on the (undocumented?) original desugaring If really needed, I think a ppx extension could even do the translation automatically. Anyway, this incompatibility should be documented. |
|
The case of python-like hashtable accessors is terrific, can't wait to see it in the official distribution. |
parsing/parser.mly
Outdated
There was a problem hiding this comment.
Here the assign variable is a string, for bigarray_function it is a boolean.
Is there a reason for that ?
Maybe we should have a unified way of calling those two functions, the boolean way seems cleaner.
There was a problem hiding this comment.
No good reason as far as I can see.
I was probably initially mimicking the original function, then realized that there was only two possible value for assign while writing bigarray_function.
bytecomp/translcore.ml
Outdated
There was a problem hiding this comment.
I tested the above lines and it wouldn't work: Translcore is linked before the arguments are evaluated, so in this case, !Clflags.fast is always set to false.
Those should go directly in the find_primitive function below.
There was a problem hiding this comment.
You are right. I have fixed this problem in the current version. Thank you for taking the time to test this point.
|
This PR have been discussed during the last developers' meeting, where I had the pleasure to be. To sum-up:
|
|
Nice to see this is considered for integration! @bolot thank you for the reports on the various pull request, It's very nice for people who can't go to developers meetings. |
This commit introduces a new syntax for index operators.
Six core parenthesis operator are added:
.(), .[], .{}, .{,}, .{,,}, .{,..,}.
The .{,}/.{,,}/.{,,,} operators are defined for compatibility with the Bigarray syntax extension.
Each core index operator is available in a access/assignement versions. For instance, .() is declined in
* .() : index operator
* .()<- : indexed assignment operator
The general syntax for these index operators as implemented in the parser is index_operator::= index_operator_core [<-]
This commit modifies the parser to use the newly defined .() and .[] operators. It also moves the definition of the standard .() and .[] operator for String/Bytes and Array to the pervasives module. Before this commit, expressions of the form array.(index) and string.(index) where desugared to Array.get[_unsafe] array index and Strinf.get[_unsafe] string index. The unsafe or unsafe version were chosen depending on the presence of the "-unsafe" compiler option. Such expression are now desugared to ( .() ) array index and ( .[] ) string index respectively. The same desugar operation is applied to array.(index) <- value which becomes ( .()<- ) array index value. In order to keep the standard semantic for the string and array index operations, these new index operators are defined in the pervasives module using new compiler primitives, e.g. let .() = "%array_opt_get". These new primitives are then mapped to safe or unsafe version depending on the the "-unsafe" compiler option. Consequently, these modifications should have no impact on existing code. With these modifications, defining custom .() and .[] operators should be easier, at the cost of losing access to the standard index operator for either array or string.
This commits modify the Bigarray syntax extension in order to facilitate the use of custom .{} operators. The compatibility with the existing Bigarray syntax has been preserved as much as possible. However, this commit will break code which use the Bigarray .{}
syntax without opening the Bigarray module first!
Like the previous commit, this commit modifies the parser to desugar bigarray1.{index} to ( .{} ) bigarray1 index. Following the bigarray syntax, the index operator used
in the desugaring changes if the index is a n-tuple:
1-tuple => .{}
2-tuple => .{,}
3-tuple => .{,,}
4 and more tuples => .{,..,}
The bigarray modules has been modified to use this new index operators. Note that this means that these index operators are not anymore accessible without opening the bigarray module.
dd3d7b3 to
36d6f39
Compare
|
@bobot Thanks for the information I have rebased the pull request and cleaned it a little following the suggestions of @thomasblanc. |
|
The 4 levels of the bigarray operators is a bit arbitrary. Could we instead expose just:
and then add a simple optimisation for the The only downside I can see is that custom operators wouldn't be able to have optimised versions for 2 and 3 indices, but they already can't optimise for 4 or higher so it doesn't seem too bad. Ideally, inlining and unboxing optimisations would remove the extra cost from array allocation anyway. |
|
I like @lpw25's suggestion because, with that approach, it would be simpler to support the array form for all indexing operators. There's nothing special about the |
|
@lpw25 I agree that the 4 levels of bigarray operators are a bit too arbitrary. .{} : Bigarray.Array1.t -> ...
.{,}: Bigarray.Array2.t -> ...and the |
|
@Octachron If the current "1, 2, 3, array" approach is kept for Bigarray compatibility is there any reason not to extend the same support to the other index operators? |
|
@hcarty The implementation of this extension would be quite straightforward. However, this feature would interfere a little with the simple version of the a.[x,y] and let p = x, y in
a.[p] are equivalent. There are not equivalent anymore when a.[x,y] = (.[,]) a x ywhereas let p = x,y in
a.[p]
= (.[]) a pOf course, fixing this problem is easy enough: if Another point is that I have the impression that most of the use of type z=Nil_zero
type 'a succ = Nil_succ
type ('ph,'a,'b,'c) Genarray.t = ( 'a,'b,'c) Genarray.t
type 'ph n_list = T : z n_list | Cons : int * 'n n_list -> 'n 'succ n_list
let ( *: ) (x:int) l = Cons x l
let ( .{} ) a:('ph,'a,'b,'c) indices:'ph n_list = ...
...Then Speaking about It would complicate the In brief, I see 3 possible stopping points
Personally, I quite like the third option. But it sounds too complex to be integrated in this pull request. |
|
You must keep it simple, and I think the statu quo is the best option in this regard. Multi-dimensional bigarrays are by now a historical curiosity, they can stay a bit peculiar. |
|
Sorry for the terse writing above (I was trying to give feedback as soon as possible to the many change proposals that have been discussed, but evidently did a bad job at communicating here). There is nothing secret about Leo's proposal, except that he prepared some slides/presentation for the meeting that are not online yet ( @lpw25 , could you make them publicly available somewhere?). It is work that originated from an effort to remove the special-casing of float arrays in the current OCaml runtime. You can find some early description of the idea in this comment on a proposal by Alain Frisch related to float arrays. Leo then developed a more complete proposal of what he calls "array data types", whose implementation can be found in his array-data-types branch, where a new type constructor for arrays is introduced with attributes to provoke various kind of specializations (mutable/immutable, unboxing, zero-termination, with the default being generic, non-float-specialized arrays). The key point of his proposal that is of concern here is to consider these specialized array types as glorified records, where the array-indexing operation It is not yet clear that this aspect of the proposal is bound to stay, but I think it is interesting enough (obviously for record projections type-based disambiguation is much more usable than scope-based usage, and as the complex discussion on shadowing warnigns show, local Having We are trying to move to a shorter release cycles, ideally six-month releases. The choice here is not to definitely reject your feature (scope-based user-defined indexing overloading), but rather to not include it in the next release (4.03) and postpone an inclusion choice to 4.04 -- hoping to have advanced in the consideration of these competing designs. Language design is a conservative affair. When I speak of a branch, I am thinking of having a (Let me point out that the Bigarray-related compatibilty woes were not instrumental in taking this decision. Nor are their your responsibility, it's clear that at the time the feature was integrated there was consensus that not special-casing Bigarray was the right choice -- but this was proved wrong by practical experience with trunk compatibility. In fact we had discussed them separately before taking this reversion decision, and had decided to go the conservative way of implicitly opening |
I didn't have any actual slides, but the branch is available at https://github.com/lpw25/ocaml/tree/array-data-types. It doesn't have any documentation to explain the syntax, since I haven't added tests yet, so that may not be very useful for understanding the feature.
I disagree. Whilst the current patch doesn't do this yet, it is sufficient to use ".()" for both regular arrays and strings (and bytes etc.), in fact that is a benefit of the proposal: ".()" becomes an explicit projection from an array(-like) block. However, it means that ".()" is always restricted to types which are implemented as array(-like) blocks. Since many other types may usefully have some notion of projection it makes sense to also separately provide an operator that can be over-loaded for those types and it seems reasonable for ".[]" to be that operator. |
|
As a side-note, my array data types proposal -- in common with ordinary labels -- supports the syntax: which avoids the need for local open. I think a similar syntax would be useful for ".[]". |
|
I have trouble to understand how you can't do all that with the current proposal + implicits (and an Indexable signature), and without more insight, I don't see how @lpw25's proposal is likely to get integrated before implicits. |
It's difficult to explain without fully explaining the proposal -- so best to wait until I've found time to do that.
The proposal is already mergeable whilst implicits still requires a huge amount of work. |
|
Thanks for taking the time to detail your comment. I have no doubt that you were well meaning in your previous comment. However, communicating decisions without the context of the decision is bound to create some frictions from time to time. If there is any plan to have some publicly available minutes of the developer meeting? It would be very nice; the difference between a secret and an information shared only with a select circle is tenuous at best. After reading the explanation for Leo proposal, it sounds like a nice feature; that does not cover any of my uses case for custom index operators (e.g dictionary, slice, multidimentionnal array or statistically checked array ) where either the data is not exactly an array block or the index is not a simple integer. In these more complex situations, I still think that it makes more sense to have scope-overloaded index operators. So I agree with @lpw45 that it might make sense to have
The shorter release cycles sounds like a good news. This is also the kind of news for which having minutes would be nice. And like I said before, I understand the thirst for further considerations -- just does not expect me to be perfectly happy if these considerations take place behind closed doors.
In this context, i.e. limited period and well-defined objective, I will be glad to lend an hand to maintain this branch. @lpw45: I agree that the syntax |
I am currently in the process of "exporting" the decisions that have been made as publicly-visible comments on the tickets that have been discussed. I did a bit yesterday (obviously I over-favoured quantity over quality of the reports), and hope to finish today. (It's actually quite a bit of work.) We do need to improve communication on release cycle decisions and such (I'm trying to mention it explicitly in the present reports), but I'm uncomfortable with the idea of exporting minutes for a meeting without having had agreement of the various participants beforehand. For this one meeting I think I'll keep a summary-only approach. (I don't expect to be present in similar meetings in the short- to medium-term future, but maybe @bobot or other participants could take a decision on this. ) |
I think a summary of the discussions (rather than full minutes) would be useful in addition to the individual feedback to PRs as it gives a single place people can read about the various discussions. I also agree that the agreement of the participants is needed before releasing such a summary. Perhaps if you wrote a small summary from your notes, and asked on caml-devel for the approval of the participants, they could be posted somewhere (although I'm not sure where the best place would be). |
|
The minutes would also be useful for caml-devel itself since not all core developers could attend the meeting. For a larger diffusion, we would also need to get the green light from non-core devel participants. |
|
@damiendoligez As far as I recall from the recent meeting it was decided that this should not be merged; do I remember correctly? If so we should probably close this. |
|
@mshinwell I have more mixed memories on this discussion, however it would be clearer to close this PR (and #622) in favor of its latest incarnation #1064 . |
|
My notes agree with @Octachron |
c703f5f Incorporate upstream comments into type-variable refactor (ocaml#121) 362ba23 Constrain curry modes to increase along applications (ocaml#108) b1f0cf9 Simplify the extension handling (ocaml#114) 4fd53a1 Remove pat_mode from typedtree (ocaml#105) cf6fcbc Handle attributes on lambdas with locally abstract types (ocaml#120) 5fa80fe Don't track attributes inside attributes for warning 53 (ocaml#115) 8a69777 Handle unclosed `[: ... :]` patterns (via `Generic_array` machinery) (ocaml#117) b0737f4 Add promote-one Makefile target (ocaml#118) c6ad684 Refactoring and fixes around module lookup (ocaml#107) b0a6495 Add documentation for global constructor arguments (ocaml#69) dd79aec Print `nlocal` in the `-d(raw)lambda` output (ocaml#112) 8035026 Fix `nlocal` in the generated Lambda for list comprehensions (ocaml#113) afbcdf0 Immutable arrays (ocaml#47) bfe1490 fix several issues when removing exp_mode (ocaml#110) 8f46060 Better error message for under-applied functions (ocaml#74) 27331d8 Consistently use Lmutvar or Lvar in comprehensions (ocaml#111) 01e965b Skip failing test for now 0131357 Fix test case to use comprehensions_experimental 22a7368 Temporarily disable list comprehensions tests due to locals bug e08377d Make `comprehensions` into `comprehensions_experimental` for now (ocaml#109) 947cf89 List and array comprehensions (ocaml#46) bd9e051 remove exp_mode from typedtree (ocaml#100) a9268d2 Fix misplaced attribute warning when using external parser (and some cleanup) (ocaml#101) 2b33f24 Refactor toplevel local escape check (ocaml#104) ed2aec6 Comment functions exported from TyVarEnv. 87838ba Move new variable creation into TyVarEnv. a3f60ab Encapsulate functions that work with tyvars 43d83a6 Prevent possibility of forgetting to re-widen 2f3dd34 Encapsulate context when narrowing type env't d78ff6d Make immediate64 things mode cross (ocaml#97) aa25ab9 Fix version number (ocaml#94) d01ffa0 Fix .depend file (ocaml#93) 942f2ab Bootstrap (ocaml#92) 05f7e38 Check Menhir version (ocaml#91) 1569b58 Move the CI jobs from 4.12 to 4.14. (ocaml#90) git-subtree-dir: ocaml git-subtree-split: c703f5f
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.2.1 to 10.2.3. - [Release notes](https://github.com/postcss/autoprefixer/releases) - [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md) - [Commits](postcss/autoprefixer@10.2.1...10.2.3) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Ocamlorg resync
This patch simplifies the definition and use of custom index operator, i.e the
operators used to access or modify the value of an array-like structure at an given index.
First, a new syntax for index operators is introduced.
Six "core parenthesis operators" are added
.(),.[],.{},.{,},.{,,},.{,..,}.The
.{,}/.{,,}/.{,,,}operators are defined for compatibility with theBigarray syntax extension (more about it later).
Each core index operator is available in an
safe/unsafe andaccess/assignmentversions. For instance,
.()is declined in.():safeindex operator.()! : unsafe index operator.()<-:safeindexed assignment operator.()!<- : unsafe indexed assignment operatorExpressions of the form array.(index), string.(index) and bigarray1.{index} are
now desugared to one of these new index operators.
The safe or unsafe indexThese new index operators respect theoperator are chosen in function of the presence or absence of the
"unsafe" compiler option.
-unsafecompiler option using new compiler primitives.
In order to keep the compatibility with existing code,
the
.()and.[]index operators are defined inside the pervasives modulesto be equal to their standard equivalent.
Compatibility issues with bigarray
The bigarray
.{}operators can be desugared to 4 different operators torespect the original bigarray syntax extension.
More precisely, the index operator used in the desugaring changes if the
index is a n-tuple. Depending on the arity of the tuple, the index operator
used is either:
.{}: arity 2 [ +1 for assignment ] operator.{,}: arity 3 [ +1 for assignment ] operator.{,,}: arity 4 [ +1 for assignment ] operator.{,..,}: arity 2 [ +1 for assignment]operator, the tuple is passed as an array.
The bigarray module have been updated to use these new operators. However,
since these operators are not defined inside pervasives, this change will
break existing code using bigarrays without opening the Bigarray module.
At least one test in the test suite has been updated due to this
incompatibility.
An other possibility to deal with this incompatibility issue
would be to hide the new desugar transform of
.{}behind a compiler switch.A possible advantage of this compiler switch option is that it would
allow to fusion all four
.{}operator. Then, the bigarrays custom.{}indexoperators could be implemented at the Bigarray.Array{n} level rather than
the Bigarray level.
Other compatibility issues
Code relying on the old desugaring to redefine the index operators will also break.
Example of code
Edited on 13/06/2014 to reflect the current version of the proposal