Replies: 13 comments 25 replies
-
Of the exported library predicates, is there currently any overlap or ambiguity in names? Also, if we consider the predicates exported by :- module(crypto, [hex_bytes/2, % ?Hex, ?Bytes crypto_n_random_bytes/2, % +N, -Bytes crypto_data_hash/3, % +Data, -Hash, +Options crypto_data_hkdf/4, % +Data, +Length, -Bytes, +Options crypto_password_hash/2, % +Password, ?Hash crypto_password_hash/3, % +Password, -Hash, +Options crypto_data_encrypt/6, % +PlainText, +Algorithm, +Key, +IV, -CipherText, +Options crypto_data_decrypt/6, % +CipherText, +Algorithm, +Key, +IV, -PlainText, +Options ed25519_seed_keypair/2, % +Seed, -KeyPair ed25519_new_keypair/1, % -KeyPair ed25519_keypair_public_key/2, % +KeyPair, +PublicKey ed25519_sign/4, % +KeyPair, +Data, -Signature, +Options ed25519_verify/4, % +PublicKey, +Data, +Signature, +Options curve25519_generator/1, % -Generator curve25519_scalar_mult/3, % +Scalar, +Point, -Result crypto_name_curve/2, % +Name, -Curve crypto_curve_order/2, % +Curve, -Order crypto_curve_generator/2, % +Curve, -Generator crypto_curve_scalar_mult/4 % +Curve, +Scalar, +Point, -Result ]). Which of these predicates is most likely to benefit from module qualification because "someone might not know what module they come from"? Probably not the majority of these predicates, the 11 predicates which start with the prefix |
Beta Was this translation helpful? Give feedback.
-
Note that there is no need to import all predicates from a module. For instance, you can use: :- use_module(library(crypto), [hex_bytes/2]). to import only |
Beta Was this translation helpful? Give feedback.
-
When reporting an issue, I recommend to use the $ scryer-prolog -f |
Beta Was this translation helpful? Give feedback.
-
Adding explicit qualification to every predicate will incur non-trivial runtime overhead, and will make reasoning about terms much harder. Unification of terms would be nightmare. There are so many other reasons... I just don't have stamina to write all of them at once :) |
Beta Was this translation helpful? Give feedback.
-
This is one of the reasons that my
I think including extra predicates is an ISO conforming extension (not sure if strictly conforming though), but one of the things that I feel is very nice of Scryer Prolog is that it doesn't do that by default1, so that it can be used to test if code is ISO compliant. I don't know if we want to put the strict ISO mode behind a flag, or if we should put the "nice" mode behind a flag instead, but I lean to the latter. I feel a good way to do that would be to introduce a Scryer prologue (different but similar in concept to the Prolog prologue). This would include a lot of standard libraries that we use a lot in Scryer Prolog (like Footnotes
|
Beta Was this translation helpful? Give feedback.
-
How are interfaces still maintained with explicit qualification in the source code? After all, any code can be reached with explicit qualification. Explicit qualification is needed at runtime in the Quintus/SICStus module system but only for these meta-arguments. I'd go so far to claim that any explicit qualification (except those with multifile/1) should be avoided. |
Beta Was this translation helpful? Give feedback.
-
I am a bit surprised this is so contested. Let's imagine a production file like this in the future: :- use_module(library(lists)).
:- use_module(library(system)).
:- use_module(library(charsio)).
:- use_module(library(format)).
:- use_module(library(random)).
:- use_module(library(debug)).
:- use_module(app_utils).
:- use_module(data_access).
:- use_module(user_interface).
:- use_module(business_logic).
:- use_module(reporting).
:- use_module(authentication).
:- use_module(domain_models/user).
:- use_module(domain_models/product, [product/4]).
:- use_module(domain_models/order, [create_order/2]).
:- use_module(services/payment_gateway, [process_payment/3]).
:- use_module(services/email_service).
:- use_module(domain_models/cart, [add_item/3, remove_item/3, get_total/1]).
:- use_module(domain_models/shipping, [calculate_shipping_cost/3]).
:- use_module(domain_models/payment, [process_refund/2]).
:- use_module(services/notification_service, [send_order_confirmation/2]).
:- use_module(reporting/sales_reports, [generate_monthly_report/1, generate_yearly_report/1]).
:- use_module(reporting/customer_reports, [get_top_customers/1, analyze_purchase_history/2]).
:- use_module(tools/data_migration, [migrate_legacy_data/0]).
:- use_module(tools/performance_testing, [run_load_test/2]).
:- use_module(ui_components/login_form).
:- use_module(ui_components/product_listing, [display_products/1]).
:- use_module(ui_components/shopping_cart, [show_cart/1, update_quantity/3]).
:- use_module(admin_tools/user_management,
[add_user/3, remove_user/2, list_users/0]).
:- use_module(admin_tools/product_management, [add_new_product/4]).
:- use_module(integrations/thirdparty_api, [fetch_data/2]). We currently have no (step-thru) debugging tools, no refactoring tools, no code exploration tools, nothing really except Let's consider the possibilities:
Right now, even with the standard library, unless you happen to be very familiar with the entire standard library, it can be difficult to know where to look for something like Now you might say, "pssssh, Jay, you're being silly. There aren't that many predicates in the standard library, and they are mostly well named, and most people aren't new for very long". Well, you might be right, but I'm not really talking about the standard library, I'm talking about people (hopefully) copying the coding style of the standard library. I am talking about application code. Which I'm assuming we want, and we don't want Scryer to be considered a hobbyist language. With a few people working on a project for 4-5 years ONLY, I have no doubt you could be looking a hundreds of files, 10s to 100s of thousands of lines of code, with a mix of standard library, 3rd party, and application files and packages. I'm honestly not sure how the idea of not module qualifying or module alias qualifying is justifiable. Let's say someone gets hired to work on a Scryer Prolog project. It is 5 years old, has had 8 full time people and 3 contractors work on it, has 125,000 lines of code in it. There's no documentation or comments because that's how real code works and the documentation/comments that exist were written in year 2 and haven't been updated since. There's a half-assed test suite, most of which are commented out. You get hired because you're an expert in Prolog and "something's not working somewhere, but we're not sure what and we're not sure where, and it only happens sometimes". If you can tell me with a straight face that you want to spend your time grepping predicate definitions, then you are a better poker player than I am! Either that or you would say, "I wouldn't take that job". But that's every job, everywhere. |
Beta Was this translation helpful? Give feedback.
-
One general comment regarding the number of predicates we expect: Due to a predicate being able to handle multiple modes, the number of library predicates that are needed to write interesting Prolog applications tends to be smaller than the number of, say, library functions in other languages. A predicate with N arguments can be invoked in 2N different modes, so a single Prolog predicate with, say, 3 arguments would tend to be expressed with 8 functions in other programming languages. This trend of order-of-magnitude reduction in library exports may be one of the reasons why this concern has so far not yet arisen. |
Beta Was this translation helpful? Give feedback.
-
@jjtolton Do you remember that I called "programming in the large" a highly debated topic? #2591 (comment) Now you see ;) |
Beta Was this translation helpful? Give feedback.
-
The other thing I will say, most of the people on this board are so experienced I would never dream of telling any of you how to write code, especially Prolog. I'm not talking about you guys, I'm talking about all the other people. The overworked engineer who hasn't slept much and has an impossible delivery schedule, and his beleaguered coworkers who need to review it. The new intern. The guy who's been doing javascript for 12 years and recently got a job here. That's why I tagged this "in the large" and not "for people who are really, really good at it". So if at any point you think I'm trying to tell you how you should write your code, I'm definitely not!! But not everyone is you. For example, I think Peter Norvig is one of the greatest Python developers there is, but his style should not be emulated. He can get away with it because he is Peter Norvig. I think some of the people on this board are on par with him, in fact @triska is the only person I've ever seen to catch a mistake in his code! So if you are already an expert, you of course can write however you like. Imagine not what rules you would want to follow yourself, but what rules you would want the worst, most malevolent, lazy programmer you can imagine to follow. Imagine they wrote 18 months of code and then it was abandoned and handed over to you with zero explanation or documentation. What rules would you have wanted that person to follow? |
Beta Was this translation helpful? Give feedback.
-
Just to stir the pot a little... A few things to notice: When I begin typing an alias, I am offered autocomplete options. When I confirm an alias and type It's a really nice workflow. As you can see, it's not much additional effort to include documentation, parameters information, cross-reference information, etc. This really looks like it would be that horrible?? |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
My goal is start steering Scryer towards use in production on larger-ish
projects. Multiple team members, team members of different experience
levels, team members who are present at different points in the
lifecycle of the project. One of the first things that comes to mind is
modules and the module system.
Note: I will often use the phrase "namespace" interchangeably
with "module". Please assume when I'm talking about Prolog and I say
"namespace", I am referring to the general concept of associating
terms with a module and that the technical version of doing that is by
using modules.
Major Points
use_module/3
or somethingsimilar, i.e.:
use_module(Module, Alias, Specifics)
builtins, and if we aren't doing that, we should probably start
treating them as builtins unless a specific restrictive flag is
present during startup
Unknowns
aren't doing these practices?)
Overview
All production languages (with the notable exception of C, in which the
lack of modules/namespaces leads to very verbose names) which are used
for large scale system processing use module or namespace qualification
when writing application code. Even C# and Java, which typically have
using
orrequire
directives which alias a class to just theclassname, still count as namespaced because they are namespaced to the
class.
In Python, for instance, it is considered very poor practice do the
following (except in very specific circumstances):
where everything in the
somelib
module is now available in theimporting module.
Likewise, in Clojure, it is considered poor practice to do
where likewise all of the
somelib
namespace is now available.In these instances, particularly because the languages are dynamic, the
last import wins and overwrites any conflicting names in earlier
imports. Worse, readability suffers.
When there are a significant number of
from X import *
statements atthe top of a Python module, it can become
extremely painful
to tracecode -- so much so that you will almost never see
from X import *
inANY (application level) Python code. (The only time it is generally
used is in packaging code to provide a flattened namespace hierarchy).
The preferred options are:
Python
Clojure
Python and Clojure have different resolution methods for arbitrating the
meaning of
something.foo
, the net result is the same.Current state of things in Scryer
.scryerrc
My
.scryerrc
module continues to grow to the point where I assumeit's going to include effectively the entire standard library.
It already currently has these:
And I'm sure that will continue to grow as time goes on.
I've noticed that I frequently forget in my examples to include
everything in my
.scryerrc
file -- this puts additional burden on thereader. As someone who is also learning Scryer, I've noticed this same
practice in everything from posts to books on Prolog, you need to
sometimes need to dig significantly even through non-code sources to
find the definition of a predicate.
Qualifying modules only when necessary
I have noticed, probably in the name of readability, that module names
are typically elided except where technically necessary for the
compiler/interepter.
This will not work with readability at scale for reasons listed above.
Suggestions
This is not to say that things such as
if_
ormember
should bequalified as
reif:if_
orlists:member
, more likely they should justbe automatically available at runtime.
However, for instance,
library(crypto)
modules probably should benamespace qualified, because they are unlikely to be commonly found in
code and out of context, someone might not know what module they come
from.
Within the application space, virtually all application code
(outside the current module) should be module qualified, and it would be
better if it could be path qualified from the project root or aliasable,
e.g,
app.lib.foo:bar/2
orapp/lib/foo:bar/2
, whatever is mostappropriate for Prolog, or aliasable perhaps with
:- use_module_alias(app/lib/foo, lib/foo)
or:- use_module_alias(app/lib/foo, lib.foo)
(whatever the case me be).In general, we should be respectful of others reading our code and
module qualify things by default rather than only when technically
necessary. Code that is so common that it shouldn't be qualified should
be included automatically by default, because by convention that's what
we're all doing with our
.scryerrc
modules anyway and this will justbe one less hurdle for newcomers when they want to try our language.
ISO-compliance
Of course we want to stay isocompliant, so we need to make this an
extension rather than a change.
Recap
use_module/3
or somethingsimilar, i.e.:
use_module(Module, Alias, Specifics)
builtins, and if we aren't doing that, we should probably start
treating them as builtins unless a specific restrictive flag is
present during startup
Please let me know what I'm overlooking, or how this is currently being
handled, criticims, and how it aligns with the goal of making Scryer
suitable for large scale projects.
Beta Was this translation helpful? Give feedback.
All reactions