Julia: السماح بالحمل الزائد على بناء جملة الوصول إلى المجال

تم إنشاؤها على ١٠ يناير ٢٠١٣  ·  249تعليقات  ·  مصدر: JuliaLang/julia

التعليق الأكثر فائدة

إليك تنفيذ ممتع من 3 أسطر لهذا:

diff --git a/base/boot.jl b/base/boot.jl
index cd3ae8b..a58bb7e 100644
--- a/base/boot.jl
+++ b/base/boot.jl
@@ -266,6 +266,9 @@ Void() = nothing

 (::Type{Tuple{}})() = ()

+struct Field{name} end
+(::Field{f})(x) where {f} = getfield(x, f)
+
 struct VecElement{T}
     value::T
     VecElement{T}(value::T) where {T} = new(value) # disable converting constructor in Core
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index b4cb4b5..59c9762 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -1685,7 +1685,7 @@
     (if (and (pair? e) (eq? (car e) '|.|))
         (let ((f (cadr e)) (x (caddr e)))
           (if (or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$))
-              `(call (core getfield) ,f ,x)
+              `(call (new (call (core apply_type) (core Field) ,x)) ,f)
               (make-fuse f (cdr x))))
         (if (and (pair? e) (eq? (car e) 'call) (dotop? (cadr e)))
             (make-fuse (undotop (cadr e)) (cddr e))

تفكيري هو أن a.b يجب أن يستدعي بالفعل وظيفة الإسقاط Field{:b}() بدلاً من getfield ، بحيث تحصل على وظائف مثل x->x.a بالفعل مجانًا. يتيح ذلك أيضًا لـ getfield أن يعني دائمًا الوصول إلى الحقل ذي المستوى المنخفض.

يعمل التطبيق أعلاه بشكل كامل ولكنه صعب جدًا على المترجم (sysimg + 5٪ ، وهو نوع من المفاجأة السارة حقًا). لذلك سيحتاج هذا إلى بعض الاستدلالات التخصصية وتحتاج بعض التحسينات المبكرة إلى التحديث ، ولكن بعد ذلك نأمل أن يكون هذا قابلاً للتطبيق.

ال 249 كومينتر

قد تكون القدرة على استخدام النقاط كسكر نحوي لطرق التحوير / الملحق أمرًا رائعًا للعديد من الأشياء. لطالما كنت أقدر هذا في اللغات التي توفرها ، بحيث يمكنك تحويل حقول البنية إلى تجريدات أكثر تعقيدًا دون كسر واجهة برمجة التطبيقات.

+1

لدي طريقة رائعة للغاية لتنفيذ هذا.

مهتم بالحديث عنها؟ أعلم أن Tom Short مهتم حقًا بالحصول على هذا من أجل DataFrames ، على الرغم من أنني أصبحت أكثر تشككًا في حكمة استخدام هذه الميزة.

هذا من شأنه أن يجعل استدعاء كود Python (عبر PyCall) أجمل بشكل كبير ، لأنني مجبر حاليًا على القيام بـ a[:b] بدلاً من a.b .

JeffBezanson ، أي فرصة للحصول على هذا 0.3؟ سيكون رائعًا للتفاعل بين اللغات ، لكل من PyCall و JavaCall (ccaviks).

JeffBezanson إذا _not_ ، هل هناك أي فرصة لإعطاء بعض التوجيهات حول كيفية تنفيذ هذا؟ ( I have an absolutely awesome way to implement this. )

من واقع خبرتي ، لا توجد طريقة أسرع أو مؤكدة لجعل جيف ينفذ شيئًا ما من تنفيذ نسخة منه لا يحبها ؛-)

الفكرة الأساسية هي أنك تنفذ

getfield(x::MyType, ::Field{:name}) = ...

حتى تتمكن من التحميل الزائد لكل حقل. يسمح ذلك بالوصول إلى الحقول "الحقيقية" لمواصلة العمل بشفافية. مع الاحتياطيات المناسبة getfield(::MyType, ::Symbol) يعمل أيضًا.

أكبر مشكلة هي أن الوحدات النمطية لها سلوك خاص فيما يتعلق بـ . . من الناحية النظرية ، ستكون هذه مجرد طريقة أخرى getfield ، لكن المشكلة هي أننا بحاجة إلى حل مراجع الوحدة النمطية _ في وقت سابق _ لأنها تتصرف بشكل أساسي مثل المتغيرات العامة. أعتقد أنه سيتعين علينا الاحتفاظ بهذه الحالة الخاصة في سلوك . . هناك أيضًا القليل من القلق بشأن كفاءة المترجم ، بسبب تحليل (# أنواع) * (# حقول) تعريفات الوظائف الإضافية. لكن من أجل ذلك سنرى فقط ما سيحدث.

JeffBezanson هل تشير أيضًا إلى سلوك const في الوحدات النمطية؟ قد يكون من المفيد أن يكون لديك نوع مستخدم يحاكي وحدة وأن يكون قادرًا على إخبار المترجم عندما تكون نتيجة البحث الديناميكي عن الحقل ثابتًا. (هناك طريقة أخرى تتمثل في البدء بوحدة فعلية وتكون قادرًا على "اصطياد" jl_get_global الفاشل وإدخال ارتباطات جديدة عند الطلب)

سأجد ذلك مفيدًا جدًا مع # 5395. ثم يكون المرء قادرًا على اعتراض استدعاء لوظيفة أو طريقة غير محددة MyMod.newfunction(new signature) وإنشاء روابط لواجهة برمجة تطبيقات (ربما كبيرة) عند الطلب. ثم يتم تخزين هذا مؤقتًا كإرتباطات ثابتة على ما أعتقد.

اسمحوا لي ، مبتدئ بسيط في جوليا ، أن أقدم بعض القلق: أعتقد أن إمكانية زيادة التحميل على مشغل النقطة قد تعني أن "نقاء" الوصول إلى المجال قد ضاع بطريقة ما.

سيفقد المستخدم المعرفة بشكل عام إذا كان فعل ab هو مجرد وصول إلى مرجع / قيمة أو إذا كان من الممكن أن تكون هناك آلية وظيفية ضخمة يتم استدعاءها من الخلف. لست متأكدًا كيف يمكن أن يكون ذلك سيئًا ، إنه مجرد شعور ...

من ناحية أخرى ، أرى أن هذه بالفعل رغبة كبيرة في بناء الجملة للعديد من الحالات (PyCall ، Dataframes ...) ، وهو أمر مفهوم تمامًا.
ربما حان الوقت .. # 2614؟

أنا أؤيد القيام بذلك.

لكن النقاء لديه ما يقوله ، حتى لو كان بإمكان المرء استخدام names(Foo) لمعرفة المكونات الحقيقية لـ Foo .

ترتبط حجة النقاء ارتباطًا وثيقًا بالاهتمام العملي الرئيسي الذي لدي ، وهو كيفية تعامل المرء مع تعارض الأسماء عندما تتداخل حقول النوع مع الأسماء التي قد تأمل في استخدامها. في DataFrames ، أعتقد أننا سنحل هذه المشكلة عن طريق حظر استخدام columns و colindex كأسماء أعمدة ، لكننا أردنا معرفة خطة الأشخاص لهذا.

أعتقد أنه يجب حظر getfield(x::MyType, ::Field{:foo}) = ... عندما يكون لدى MyType حقل foo ، وإلا فسيتم فقد الوصول إلى الحقل الحقيقي (أو طريقة لفرض الوصول إلى الحقل يجب أن تكون متاحة).
ولكن بعد ذلك لا يمكن تعريف getfield إلا للأنواع الملموسة ، نظرًا لأن الأنواع المجردة لا تعرف شيئًا عن الحقول.

(في غضون ذلك ، عثرت على هذا حول C ++ .)

إنها ليست مشكلة كبيرة. يمكننا تقديم شيء مثل Core.getfield(x, :f) لفرض الوصول إلى الحقول الحقيقية.

حسنًا ، ربما تم بيعي. ولكن بعد ذلك ، سيكون تحديد اختصار لـ Core.getfield(x, :f) (على سبيل المثال ، x..f ) أمرًا رائعًا ، وإلا فإن الكود الداخلي للأنواع يزيد من تحميل . لجميع الرموز (إطارات البيانات ، وربما القواميس) تكون مزدحمة بـ Core.getfield s.

لست قلقًا بشأن جانب النقاء - حتى نحصل على هذا ، الرمز الوحيد
التي يجب أن تستخدم حق الوصول على الإطلاق هي رمز ينتمي إلى
تنفيذ نوع معين. عندما يكون الوصول إلى المجال جزءًا من واجهة برمجة تطبيقات ، فأنت
يجب توثيقه ، كما هو الحال مع أي واجهة برمجة تطبيقات. أوافق على أنه قد يكون في متناول اليد
بعض بناء جملة الاختصارات لـ core.getfield ، عند كتابتها
تطبيقات.

لقد تمت الإشارة إليه بالفعل في # 4935 ، ولكن دعنا نسحبه إلى هنا: يمكن أن يتداخل التحميل الزائد للنقاط قليلاً مع الإرسال المتعدد جوليان الكلاسيكي إذا لم يتم استخدامه بشكل صحيح ، حيث يمكننا البدء في القيام بذلك

getfield (x :: MyType، :: Field {: size}) = .........
لأني = 1: ص الحجم .....

بدلا من

الحجم (x :: MyType) = ..........
بالنسبة إلى i = 1: الحجم (y) ....

في حين أن النقطة ستكون رائعة للوصول إلى العناصر في المجموعات (Dataframes ، Dicts ، PyObjects) ، يمكنها بطريقة ما تغيير طريقة الوصول إلى خصائص الكائن (وليس الحقول).

أعتقد أن أحد الأشياء التي يجب مراعاتها هو أنه إذا كان بإمكانك زيادة التحميل على حقل الوصول ، فيجب أن تكون قادرًا أيضًا على زيادة التحميل _إعداد_ حقل. وإلا سيكون هذا غير متسق ومحبط. هل أنت بخير للذهاب إلى هذا الحد؟

nalimilan ، يحتاج المرء تمامًا إلى setfield! بالإضافة إلى getfield . (على غرار setindex! مقابل getindex مقابل [] ). لا أعتقد أن هذا مثير للجدل.

أتفق مع stevengj : سيتم بالتأكيد تنفيذ DataFrames setfield! للأعمدة.

أنا أؤيد هذا.

تُظهر الخبرة مع اللغات الأخرى (مثل C # و Python) أن بناء الجملة النقطي له الكثير من القيمة العملية. الطريقة التي يتم تنفيذها من خلال الأساليب المتخصصة تعالج إلى حد كبير القلق من تراجع الأداء.

ومع ذلك ، من المهم التأكد من أن _inlineability_ طريقة ما لن تتأثر بشكل خطير بهذا التغيير. على سبيل المثال ، شيء مثل f(x) = g(x.a) + h(x.b) لن يصبح فجأة غير قابل للإصلاح بعد هذا الهبوط.

إذا قررنا تحقيق ذلك ، فمن المفيد أيضًا توفير وحدات ماكرو لتسهيل تعريف الخاصية ، والتي قد تبدو كما يلي:

# let A be a type, and foo a property name
<strong i="10">@property</strong> (a::A).foo = begin
    # compute the return the property value
end

# for simpler cases, this can be simplified to
<strong i="11">@property</strong> (a::A).foo2 = (2 * a.foo)

# set property 
<strong i="12">@setproperty</strong> (a::A).foo v::V begin
    # codes for setting value v to a property a.foo
end

وراء الكواليس ، يمكن ترجمة كل هذه إلى تعريفات الطريقة.

لست مقتنعًا بأن <strong i="5">@property</strong> (a::A).foo = أسهل بكثير من getproperty(a::A, ::Field{foo}) = ...

على أي حال ، فإن السكر النحوي الأفضل هو شيء يمكن إضافته بعد هبوط الوظائف الأساسية.

فيما يتعلق بالتضمين ، طالما أن الوصول إلى الحقل مضمّن قبل اتخاذ القرار بشأن تضمين الوظيفة المحيطة ، فأنا لا أرى سبب تأثرها. ولكن ربما لم يكن هذا هو الترتيب الذي يتم به إجراء عملية التضمين حاليًا؟

getproperty(a::A, ::Field{:foo}) = لي

قلقي هو ما إذا كان هذا سيؤدي إلى تراجع الأداء لست واضحًا جدًا بشأن آلية إنشاء الكود الداخلي. JeffBezanson ربما يقول شيئا عن هذا؟

الوصول إلى المجال منخفض جدًا ، لذلك لن أفعل ذلك دون التأكد من الحفاظ على الأداء.

بعد كل شيء ، لست مقتنعًا بأن التحميل الزائد للحقول فكرة جيدة. مع هذا الاقتراح ، ستكون هناك دائمًا طريقتان لتعيين خاصية: x.property = value و property!(x, value) . إذا تم تنفيذ التحميل الزائد للحقل ، فسنحتاج إلى دليل أسلوب قوي للغاية لتجنب الانتهاء من الفوضى الكاملة حيث لا تعرف مسبقًا الحل الذي اختاره المؤلف لنوع معين.

وبعد ذلك سيكون هناك سؤال حول ما إذا كانت الحقول عامة أم خاصة. عدم السماح بالحمل الزائد للحقل سيجعل نظام النوع أكثر وضوحًا: ستكون الحقول دائمًا خاصة. ستكون الطرق عامة ، وستكون الأنواع قادرة على إعلان أنها تنفذ واجهات / بروتوكول / سمات ، أي أنها توفر مجموعة معينة من الأساليب. هذا من شأنه أن يتعارضstevengj الصورة https://github.com/JuliaLang/julia/issues/1974#issuecomment -12083268 عن الحمولة الزائدة المجالات مع طرق لتجنب كسر على API: لا تقدم سوى أساليب كجزء من API، وأبدا الحقول .

المكان الوحيد الذي أندم فيه على زيادة التحميل على الحقل هو DataFrames ، نظرًا لأن df[:a] ليس جيدًا مثل df.a . لكن هذا لا يبدو أنه يجب أن يتطلب بمفرده مثل هذا التغيير الكبير. يبدو أن حالة الاستخدام الأخرى هي PyCall ، مما قد يشير إلى أنه يجب السماح بالحمل الزائد للحقل ، ولكن فقط لحالات استخدام غير جوليانية شديدة التحديد. ولكن كيف يمكن منع الأشخاص من إساءة استخدام الميزة بمجرد توفرها؟ إخفاء ذلك في وحدة خاصة؟

nalimilan ، أود أن أقول إن الأفضلية هي استخدام بناء جملة x.property قدر الإمكان. الشيء هو أن الناس _ حقًا_ يحبون بناء الجملة هذا - إنه ممتع للغاية. يبدو أن أخذ مثل هذا النحو اللطيف والقول تحديدًا بأنه يجب استخدامه فقط للوصول الداخلي إلى الأشياء منحرف تمامًا - "هاه ، هذا التركيب الجميل موجود ؛ لا تستخدمه!" يبدو من المنطقي أكثر أن نجعل بناء الجملة للوصول إلى الأشياء الخاصة أقل ملاءمة وجمالًا بدلاً من إجبار واجهات برمجة التطبيقات على استخدام البنية القبيحة. ربما تكون هذه حالة استخدام جيدة لعامل التشغيل .. : مشغل الوصول إلى الحقل _real_ الخاص.

أعتقد في الواقع أن هذا التغيير يمكن أن يجعل الأمور أكثر وضوحًا واتساقًا وليس أقل من ذلك. ضع في اعتبارك النطاقات - يوجد حاليًا نوع من مزيج بشع من أنماط step(r) مقابل r.step الأنماط الموجودة الآن. خاصة وأنني قدمت FloatRange فهذا أمر خطير لأن الكود الذي يستخدم step(r) هو الصحيح. والسبب في هذا المزيج هو تخزين بعض خصائص النطاقات وبعضها محسوب - لكن تلك الخصائص تغيرت بمرور الوقت وهي في الواقع مختلفة لأنواع النطاقات المختلفة. سيكون أسلوبًا أفضل إذا كان كل وصول من النمط step(r) باستثناء تعريف step(r) نفسه. لكن هناك بعض الحواجز النفسية الشديدة التي تحول دون ذلك. إذا جعلنا r.step استدعاء طريقة يتم تعيينه افتراضيًا على r..step ، فعندئذ يمكن للأشخاص فعل ما يميلون إليه بشكل طبيعي.

للعب دور محامي الشيطان (مع نفسي) ، هل يجب أن نكتب r.length أم length(r) ؟ التناقض بين الوظائف والأساليب العامة مشكلة أصابت بايثون ، بينما التزم روبي تمامًا بالنمط r.length .

+1 لـ .. كـ Core.getfield !

StefanKarpinski أمر منطقي ، ولكن بعد ذلك ستحتاج إلى إضافة بناء جملة للحقول الخاصة ، وسيتعين على الواجهات تحديد كل من الأساليب والحقول العامة. وبالفعل أنت بحاجة إلى دليل أسلوب لضمان بعض الاتساق ؛ حالة length حالة صعبة ، ولكن هناك أيضًا على سبيل المثال size ، وهو مشابه جدًا ولكنه يحتاج إلى مؤشر بعد. هذا القرار يفتح علبة من الديدان ...

في هذه الحالة ، أؤيد أيضًا .. للوصول إلى الحقول الفعلية ، و . للوصول إلى الحقول ، سواء كانت أساليب أو قيمًا حقيقية.

للعب دور محامي الشيطان (مع نفسي) ، هل يجب أن نكتب r.length أو length(r) ؟ التناقض بين الوظائف والأساليب العامة مشكلة أصابت بايثون ، بينما التزم روبي تمامًا بالنمط r.length .

العامل الرئيسي الذي قد يكون واضحًا لهذه المشكلة هو ما إذا كنت تريد أن تكون قادرًا على استخدام شيء ما كوظيفة ترتيب أعلى أم لا. أي f في f(x) هو شيء يمكنك map على مجموعة ، بينما f في x.f ليس (قصير الكتابة x -> x.f ) - وهو نفس الموقف لجميع الطرق بلغات الإرسال الفردي.

لماذا تتوقف عند الوصول الميداني؟ ماذا عن وجود x.foo(args...) ما يعادل getfield(x::MyType, ::Field{:foo}, args...) = ... ؟ ثم يمكن أن يكون لدينا x.size(1) للحجم على طول البعد الأول. (لست متأكدًا مما إذا كنت مغرمًا باقتراحي ، ولكن ربما هناك شيء يجب مراعاته. أو ربما لا ، لأن الناس سيكتبون كود OO مشابه؟)

سيكون ذلك ممكنًا مع هذه الوظيفة. وهو أحد الأشياء التي تجعلني أتوقف. ليس لدي مشكلة في كود نمط oo من هذا القبيل - كما قلت ، إنه ممتع إلى حد ما ويعجبه الناس حقًا - ولكنه يقدم خيارات كافية في طرق كتابة الأشياء التي نحتاج - حقًا - إلى سياسة قوية حول ما يجب عليك فعله لأنك ستكون حراً للغاية فيما يمكنك القيام به.

عندما بدأت في تعلم جوليا ، ساعدتني صيغة no-dot كثيرًا على التخلي عقليًا عن أسلوب البرمجة OO. لهذا السبب وحده ، أعتقد أن اقتراحي سيء.

أيضًا ، من أجل التحميل الزائد البسيط (على سبيل المثال فقط a.b sans (args...) ) ، أتفق مع تعليق nalimilan أعلاه. في الإصدار رقم 4935 ، يبدو أن الإجماع هو أن الحقول لا يجب أن تكون جزءًا من واجهة برمجة التطبيقات (API) ولكن فقط الأساليب ؛ وبالتالي يبدو أنه سيتم إغلاق هذه القضية. إن وجود بناء جملة overloading . سيجعل الأمر أقل وضوحًا بكثير من أن الحقول العادية لا ينبغي أن تكون جزءًا من واجهة برمجة التطبيقات وربما تشجع على جعل الحقول جزءًا من واجهة برمجة التطبيقات.

لكن نعم ، بناء الجملة . مناسب ...

ماذا عن: يجب أن يكون المفرد . _only_ سكرًا نحويًا لـ getfield(x::MyType, ::Field{:name}) = ... والوصول إلى الحقل _ فقط_ من خلال .. (أي ما . الآن).

سيسمح هذا بالتمييز الواضح:

  • . لواجهة برمجة التطبيقات العامة للوصول إلى أشياء تشبه القيمة من مثيلات النوع
  • .. مخصص للوصول إلى الحقل ويجب عدم استخدامه بشكل عام في واجهة برمجة التطبيقات العامة

بالطبع ، سيكون هذا تغييرًا جذريًا.

هذا هو ما كنت أقترحه بشكل أساسي ، باستثناء أن . الافتراضي هو .. لذلك لا ينكسر.

آسف ، كان يجب أن أعيد القراءة!

لكني أعتقد أن . لم يكن يتخلف عن السداد إلى .. قد يكون جيدًا بالفعل (بصرف النظر عن أنه كسر) ، لأنه سيفرض قرارًا على المطور بشأن ما هو API العام وما هو غير ذلك. أيضًا ، إذا كان المستخدم يستخدم .. فإنه يتوقع أن الكود الخاص به قد ينكسر ، بينما . لا يجب أن يفعل.

هذه نقطة جيدة. يمكننا السير في هذا المسار من خلال جعل a.b افتراضيًا إلى a..b مع تحذير الإيقاف.

من منظور الأسلوب ، أعتقد أنني أفضل كثيرًا رؤيته

a = [1:10]
a.length()
a.size()

من

a.length
a.size

أعتقد أنه يساعد في الحفاظ على فكرة استدعاء وظيفة بدلاً من مجرد استرداد خاصية مخزنة بطريقة ما في النوع (عودة إلى مشكلة "النقاء" أعلاه). أتساءل عما إذا كانت هناك طريقة للمساعدة في ضمان هذا النوع من الأسلوب حتى لا تصبح الأمور فوضوية كما هي في بعض اللغات الأخرى.

أنا حقا لا أحب

a.length()

منذ ذلك الحين لا يمكنني معرفة ما إذا كان هناك حقل دالة في النوع الأصلي. إذا لم يصل . إلى الحقول مطلقًا ، فمن الواضح أن هذه ليست مشكلة. خلاف ذلك ، يبدو لي محيرا.

بداهة ، أشعر أننا لا يجب أن نفعل إما a.length() أو a.length . لكن السؤال لماذا؟ ما الذي يجعل r.step مختلفًا عن r.length ؟ هل هو مختلف؟ إذا لم تكن مختلفة ، فهل يجب علينا استخدام step(r) و length(r) أو r.step و r.length ؟

باستخدام الدلالات التي اقترحها ستيفان والإضافة التي قمت بها ، سيكون من الواضح أن . دائمًا هو استدعاء دالة (تمامًا مثل + أيضًا) ، بينما .. دائمًا حقل التمكن من.

فيما يتعلق بمسألة ما إذا كان a.length ، وما إلى ذلك فكرة جيدة: ماذا عن . يجب استخدام الوصول فقط للوصول إلى البيانات الفعلية في النوع ، أكثر أو أقل كما يستخدم المرء إدخالات . بينما نلتزم بالوظائف الخاصة بخصائص عدم وجود بيانات مثل ، size ، length ، step إلخ. لأن بعضها سيحتاج إلى معلمات إضافية ، وأعتقد أن a.size(1) نوع بناء الجملة سيء.

إليكم رأيي في هذا الموضوع:

  • يجب استخدام صيغة النقطة فقط لسمات من النوع / الفئة. يرجى أن تضع في اعتبارك أن هذا لا يتعلق فقط بالحسابات ولكن أيضًا بالمحددات وشيء مثل a.property() = ... يبدو خاطئًا تمامًا.
  • على الرغم من أنني أحب الوضع الحالي حيث تحدد الوظيفة واجهة برمجة التطبيقات العامة وتكون الحقول خاصة ، إلا أنني أشارك ستيفانز رأيها بأن بناء جملة النقطة لطيف جدًا بحيث لا يمكن حظره لواجهات برمجة التطبيقات العامة. ولكن من فضلك دعنا نقصر هذا على سمات بسيطة. a.length مثال جيد ، a.size(1) ليس لأنه يتطلب وسيطة إضافية.
  • الرجاء السماح لـ . افتراضيًا لـ .. . جوليا ليست معروفة بأنها لغة معيارية. دعونا تبقى على هذا النحو

الرجاء السماح لـ . افتراضيًا لـ .. . جوليا ليست معروفة بأنها لغة معيارية. دعونا تبقى على هذا النحو

أنا أميل إلى الموافقة على هذا. بناء الجملة لتعيين خاصية تركيبية سيكون a.property = b ، وليس a.property() = b .

بالتأكيد ، أردت فقط أن أوضح لماذا a.property() باعتباره بناء الجملة ليس جيدًا IMHO

أو بشكل أكثر وضوحًا: الشيء المهم في بناء جملة النقطة ليس أنه يمكن للمرء أن يربط بين الوظائف والأنواع / الفئات ولكن قدرتها على كتابة المحاضر / المحددات بطريقة لطيفة. تعتبر أدوات الحاصل / المحددات مهمة لتغليف البيانات (حافظ على استقرار الواجهة ولكن مع تغيير التنفيذ)

سيكون هذا التغيير رائعًا من منظور مصممي واجهة برمجة التطبيقات ، لكنني أوافق على أنه يجب أن يأتي مع نوع من دليل الأسلوب للحد من أي تضارب في المستقبل.

هذا سيمكن روبي مثل dsl ...

amt = 1.dollar + 2.dollars + 3.dollars.20.cents 

لكن كن مستعدا لجافا مثل الجنون:

object.propert1.property2.property3 ....

فقط بعض الأفكار:

  • أريد في الغالب بناء جملة . لـ Dicts مع الرموز كمفاتيح. من الأجمل استخدام d.key ثم d[:key] . لكنها في النهاية ليست حرجة.
  • أعتقد أن قراءة a->property أفضل من a..property . لكن مرة أخرى ، هذه ليست صفقة كبيرة ولا أعرف ما إذا كانت ستعمل مع بناء جملة جوليا.

BobPortmann أنا لا أوافق. القاموس هو كائن حاوية ، واجهة برمجة التطبيقات لكائنات الحاوية هي obj [index] أو obj [مفتاح]. في الوقت الحالي نظرًا لعدم وجود خصائص لدينا في Julia ، تم تحميل واجهة برمجة تطبيقات الحاوية بشكل زائد لتوفير هذه الوظيفة في مكتبات مثل PyCall و OpenCL. يساعد هذا التغيير على تقوية تمييز واجهة برمجة تطبيقات الحاوية حيث لن يتم تحميلها بشكل زائد لتوفير وظائف إضافية.

سيكون استخدام a->property للحقول الخاصة طريقة جيدة لإبعاد متسللي C عن Julia ؛-)

أنا مثل بناء الجملة .. .

تم التحدث بالفعل عن بناء الجملة a->property - هذه وظيفة مجهولة. ومع ذلك ، فإن عامل التشغيل a..b كان جاهزًا لفترة من الوقت. هناك بعض الحالات التي تريد فيها شيئًا يشبه الديكت ولكن به الكثير من الحقول الاختيارية. استخدام صيغة getter / setter لذلك سيكون أجمل من صيغة فهرسة الدكت.

"تم التحدث بالفعل عن بناء جملة الخاصية a-> - إنها وظيفة مجهولة."

نعم طبعا. لا يبدو الأمر بدون مسافات حول -> .

كدليل إرشادي للنمط ، ماذا عن التوصية باستخدام الخاصية (x) لخصائص القراءة فقط واستخدام الخاصية x لخصائص القراءة / الكتابة؟

بالنسبة للخصائص القابلة للكتابة ، فإن x.foo = bar أجمل كثيرًا من set_foo! (x، bar).

وجود foo(x) للقراءة و x.foo للكتابة أمر محير للغاية. في الواقع هذا ما تجعله الخصائص جذابة للغاية. امتلاك نفس الصيغة للوصول للقراءة والكتابة ، أي أبسط بناء يمكن للمرء الحصول عليه (للأحرف والمحددات)

فيما يتعلق بالأسلوب ، هناك السؤال الكبير عما إذا كنا نريد الحصول على كل من x.length و length(x) إذا تم تنفيذ هذه الميزة أو ما إذا كان يجب إهمال النموذج الأحدث وإزالته.

رأيي هو أنه يجب أن يكون لدينا طريقة واحدة فقط للقيام بذلك وأن نستخدم فقط x.length في المستقبل. وفيما يتعلق بالأسلوب أعتقد أنه بسيط للغاية. كل ما يعتبر خاصية بسيطة لنوع ما يجب تنفيذه باستخدام صيغة الحقل. كل شيء آخر مع وظائف. لقد استخدمت الخصائص في C # كثيرًا ونادراً ما وجدت حالة لم أكن متأكدًا فيها مما إذا كان يجب أن يكون شيء ما ملكية أم لا.

أنا ضد تغيير مجموعة مختارة عشوائيًا من دوال الوسيطة الواحدة إلى بناء جملة x.f . أعتقد أن @ mauro3 أوضحت نقطة جيدة مفادها أن القيام بذلك يحجب طبيعة اللغة.

a.b هو ، على الأقل بصريًا ، نوعًا من بناء النطاق. لا يلزم أن يكون b معرّفًا مرئيًا عالميًا. هذا فرق حاسم. على سبيل المثال ، تحليل عوامل المصفوفة مع الجزء العلوي لها خاصية .U ، لكن هذا ليس شيئًا عامًا - لا نريد دالة عالمية U . بالطبع هذا أمر شخصي بعض الشيء ، خاصة أنه يمكنك بسهولة تحديد U(x) = x.U . لكن length هو نوع مختلف من الأشياء. من المفيد أكثر أن تكون من الدرجة الأولى (مثل map(length, lst) ).

فيما يلي الإرشادات التي أود اقتراحها. يكون الترميز foo.bar مناسبًا عندما:

  1. foo يحتوي بالفعل على حقل باسم bar . مثال: (1:10).start .
  2. foo هو مثيل لمجموعة من الأنواع ذات الصلة ، بعضها يحتوي بالفعل على حقل باسم .bar ؛ حتى إذا كان foo لا يحتوي فعليًا على حقل bar ، فإن قيمة هذا الحقل متضمنة من خلال نوعه. أمثلة: (1:10).step ، (0.1:0.1:0.3).step .
  3. على الرغم من أن foo لا يخزن صراحةً bar ، فإنه يخزن معلومات مكافئة في شكل أكثر إحكاما أو كفاءة أقل ملاءمة للاستخدام. مثال: lufact(rand(5,5)).U .
  4. أنت تحاكي واجهة برمجة تطبيقات من واجهة أخرى مثل Python أو Java.

قد يكون من المنطقي أن يتم bar خاصية bar وهذا يعني ضمنيًا من هذا النوع. في مثل هذه الحالات ، ربما تريد عدم السماح بطفرة خاصية bar للأنواع الأخرى ذات الصلة ، إما بجعلها غير قابلة للتغيير أو بجعل foo.bar = baz خطأ.

tknopp ، لم أكن أقترح استخدام x.foo للكتابة و foo(x) للقراءة. كان اقتراحي أن _if_ خاصية ما قابلة للقراءة والكتابة ، فربما تريد أن تقرأها وتكتبها باستخدام x.foo .

StefanKarpinski : لكن أليس length حالة من 3. حيث الأحجام هي ما يتم تخزينه عادةً و length منتج الأحجام؟

أرى جيفز يشير إلى أن هذا التغيير سيجعل هذه الوظائف ليست من الدرجة الأولى بعد الآن.

stevengj : فهمت. آسف على الخلط بين ذلك.

tknopp - الطول مشتق من الأحجام ، لكن لا يساويها. إذا كنت تعرف الأحجام ، فيمكنك حساب الطول ولكن ليس العكس. بالطبع ، هذا خط غير واضح بعض الشيء. السبب الرئيسي في قبول هذا lufact هو أننا لم نكتشف واجهة برمجة تطبيقات أفضل من ذلك. هناك طريقة أخرى تتمثل في تحديد الدالات العامة upper و lower التي تعطي الأجزاء المثلثية العليا والمثلث السفلي للمصفوفات العامة. ومع ذلك ، فإن هذا النهج لا يعمم على عوامل QR ، على سبيل المثال.

إنه يخبرنا أنه لا يوجد سوى عدد قليل من الحالات التي يبدو أنها - حقًا - تطلب بناء الجملة هذا: pycall ، و Factorizations ، وربما أطر البيانات.
أنا قلق جدًا من أن ينتهي الأمر بمزيج عشوائي من f(x) مقابل x.f ؛ سيجعل تعلم النظام أكثر صعوبة.

ألا تعني النقطة 1 من قائمة StefanKarpinski أن أي حقل من نوع ما ينتمي تلقائيًا إلى API العام؟

في الوقت الحالي يمكنني تحديد واجهة برمجة التطبيقات العامة للوحدة النمطية: جميع الوظائف والأنواع المصدرة (ولكن ليس حقولها). بعد هذا التغيير ، لن يكون من الممكن معرفة الحقول التي من المفترض أن تنتمي إلى واجهة برمجة التطبيقات العامة وأيها لا. يمكننا البدء في تسمية الحقول الخاصة a._foo أو ما شابه ، كما هو الحال في Python ، لكن هذا لا يبدو جيدًا.

أنا شخصياً أعتقد أن حالة DataFrames غير ضرورية بعض الشيء. إذا فعلنا ذلك ، فسأضيف الوظيفة إلى DataFrames ، لكني أجد فقدان التناسق أكثر صعوبة من حفظ بعض الأحرف.

لن أتخذ القرار أيضًا بناءً على DataFrames و PyCall (ويريده Gtk أيضًا). إما أننا نريدها لأننا نعتقد أن الحقول يجب أن تكون جزءًا من واجهة عامة (لأنها "تبدو جميلة") أو لا نريدها.

... pycall ...

و JavaCall

نظرًا لأن حالة الاستخدام الرئيسية لهذا يبدو أنها تفاعلات مع أنظمة غير جوليا ، فماذا عن استخدام عامل التشغيل المقترح .. بدلاً من التحميل الزائد على . ؟

أتساءل عما إذا كان الحل الأبسط هنا هو نصيحة أكثر عمومية لـ OO:

#we already do
A[b] => getindex(A,b)
#we could have
A.b(args...) => b(A, args...)
# while
A..b => getfield(A,::Field{:b})
# with default
getfield(A, ::Field{:b}) = getfield(A, :b)

يبدو أن هذا سيسمح لـ JavaCall / PyCall بعمل تعريفات للطريقة "في" الفئات ، مع السماح أيضًا بنمط عام إذا كان الأشخاص يريدون الحصول على كود من نوع OO ، على الرغم من أنه شفاف للغاية A.b() هو مجرد إعادة كتابة. أعتقد أن هذا سيكون طبيعيًا جدًا للأشخاص القادمين من OO.
أيضًا الحصول على getfield مع A..b للسماح بالحمل الزائد هناك ، على الرغم من أن التحميل الزائد هنا لا يُنصح بشدة واستخدامه فقط لخصائص تشبه الحقول (أظن أنه لن يتم استخدامه على نطاق واسع جدًا بسبب النقص الطفيف في التحميل الزائد على getfield(A, ::Field{:field}) .

@ mauro3 :

ألا تعني النقطة 1 من قائمة StefanKarpinski أن أي حقل من نوع ما ينتمي تلقائيًا إلى API العام؟

كانت هذه قائمة بالأوقات التي لا بأس من استخدام تدوين foo.bar ، وليس عندما يكون ذلك ضروريًا. يمكنك تعطيل الترميز foo.bar للحقول "الخاصة" ، والتي لن يمكن الوصول إليها إلا عبر foo..bar .

karbarcca : لست واضحًا تمامًا بشأن ما

fwiw ، أنا من المعجبين باتباع نهج الموافقة على البالغين وفقًا للاتفاقية وجعل . مفرطًا بالكامل. أعتقد أن اقتراح النقطة المزدوجة سيؤدي إلى مزيد من الارتباك وليس تقليله.

ihnorton - كما لو كنت ضد استخدام a..b باعتباره بناء الجملة الأساسي (غير قابل للحمل) للوصول إلى الحقل أو ضد استخدام a..b للصيغة الزائدة؟

واحدة من أفضل ميزات جوليا هي بساطتها. يبدو التحميل الزائد على x.y بمثابة الخطوة الأولى على الطريق إلى ++ C.

StefanKarpinski ولكن هذا يعني تحولًا كبيرًا في النموذج من الحقول الخاصة الافتراضية إلى الحقول العامة الافتراضية.

أدركت للتو ، ربما كان هذا واضحًا للآخرين طوال الوقت. يمكن إجراء البرمجة الكاملة بأسلوب OO باستخدام التحميل الزائد الأساسي . (وإن كان قبيحًا). تعريف

getfield(x::MyType, ::Field{:foo}) = args -> foofun(x, args...) # a method, i.e. returns a function
getfield(x::MyType, ::Field{:bar}) = x..bar+2                  # field access, i.e. returns a value

ثم x.foo(a,b) و x.bar العمل. لذا فإن النقاش حول ما إذا كان يجب تنفيذ x.size(1) أو x.size هو محل نقاش.

StefanKarpinski مقابل التحميل الزائد بشكل عام a..b و فاتر حول a..b -> Core.getfield(a,b) .

بدأت أرى الحاجة إلى مشغل آخر هنا ، لكن a..b ليس مقنعًا تمامًا. الحاجة إلى شخصيتين تبدو غاية ... الدرجة الثانية. ربما a@b أو a$b أو a|b (لا يتم استخدام معاملات البت كثيرًا). الاحتمال الخارجي أيضًا هو a b` ، والذي من المحتمل أن يميزه المحلل اللغوي عن الأوامر.

سأكون موافقًا على استخدام عامل التشغيل "القبيح" للوصول البدائي إلى الحقل. أعتقد أن التجربة أظهرت أنه نظرًا لكونها عملية ملموسة ، فإنها نادرًا ما تستخدم ، بل إنها خطيرة إلى حد ما.

أقترح السماح بمحاكاة إرسال واحد OO من خلال الاتفاقية / إعادة الكتابة:

type Type end
# I can define methods with my Type as 1st argument
method(T, args...) = # method body
t = Type()
# then I can call that method, exactly like Java/Python methods, via:
t.method(args...)
# so
t.method(args...) 
# is just a rewrite to
method(t, args...)

التبرير هنا هو أننا نقوم بالفعل بإعادة كتابة بناء جملة مماثلة لـ getindex / setindex! ، لذلك دعونا نسمح ببناء جملة OO الكامل مع هذا. بهذه الطريقة ، لا يتعين على PyCall و JavaCall القيام بذلك

my_dna[:find]("ACT")
# they can do
my_dna.find("ACT")
# by defining the appropriate find( ::PyObject, args...) method when importing modules from Python/Java

يعجبني هذا لأنه تحول واضح إلى حد ما ، تمامًا مثل getindex / setindex ، ولكنه يسمح بمحاكاة إرسال واحد لنظام OO إذا رغبت في ذلك ، خاصة لحزم لغة OO.

ثم كنت أقترح استخدام عامل التشغيل .. للوصول إلى الحقل ، مع خيار التحميل الزائد. سيكون الاستخدام هنا هو السماح لـ PyCall / JavaCall بمحاكاة الوصول إلى الحقل عن طريق التحميل الزائد للمكالمات إلى .. ، مما يسمح لـ DataFrames بزيادة تحميل .. للوصول إلى الأعمدة ، إلخ. سيكون هذا أيضًا هو الوصول الافتراضي الجديد للحقل في عام لأي نوع.

لديّ مكان ضعيف لإعادة الكتابة النحوية الخالصة. يمكن القول إنه أمر سيء أن تكتب a.f(x) الآن وتجعله يعمل ولكن يعني شيئًا مختلفًا بشكل مربك عن معظم لغات OO.

بالطبع الجانب الآخر من تلك العملة هو تجزئة أسلوب فظيع ، وحقيقة أن a.f لا يشترك في أي شيء مع a.f() ، مما تسبب في انهيار الوهم بسرعة.

واحدة من أفضل ميزات جوليا هي بساطتها. يبدو التحميل الزائد على x.y بمثابة الخطوة الأولى على الطريق إلى ++ C.

نفس الشعور هنا. كنت أفكر ، إذا كانت الحاجة الفعلية لذلك هي حقًا لعدد محدود من أنواع التشغيل المتداخل ، فماذا عن جعلها صالحة فقط إذا طُلب منها صراحةً في إعلان النوع؟ على سبيل المثال ، يمكن أن تكون الكلمة الأساسية الإضافية إلى جانب type و immutable ootype أو شيء من هذا القبيل.

وحقيقة أن af لا تشترك مع af () ، مما يتسبب في انهيار الوهم بسرعة.

هل يمكنك توضيح ما يعنيه هذاJeffBezanson؟

أتوقع أن a.f هو نوع من كائن الأسلوب إذا كان a.f() يعمل.

آه ، حسنًا. نعم ، بالتأكيد لن تكون قادرًا على القيام بشيء مثل map(t.method,collection) .

سأتفق مع obj.method(...) ، هناك خطر يتمثل في أن المستخدمين الجدد قد يرون جوليا كلغة أخرى موجهة للكائنات تحاول التنافس مع Python و ruby ​​وما إلى ذلك ، ولا يقدرونها تمامًا الذهول الذي هو متعدد الإرسال. الخطر الآخر هو أن أسلوب oo القياسي يصبح سائدًا ، حيث أن هذا هو ما يعرفه المستخدمون أكثر ، على عكس النمط جوليان الذي تم تطويره حتى الآن.

نظرًا لأن حالة الاستخدام ، بخلاف DataFrames ، مقصورة على inter-op مع لغات oo ، فهل يمكن التعامل مع هذا كله بواسطة وحدات الماكرو؟ أي أن <strong i="8">@oo</strong> obj.method(a) يصبح method(obj,a) ؟

Karbarcca @ هذا يعني أنه يمكن كتابة كل شيء تلقائيًا بطريقتين:

x = 3
x.sin()
sin(x)
x + 2
x.+(2) # ?!

karbarcca https://github.com/JuliaLang/julia/issues/1974#issuecomment -38830330

طريقة t (أرغس ...)
# هو مجرد إعادة كتابة ل
طريقة (t ، args ...)

لن يكون ذلك ضروريًا لـ PyCall نظرًا لأن النقطة القابلة للتحميل الزائد يمكن استخدامها فقط لاستدعاء pyobj[:func] بواسطة pyobj.func . ثم pyobj.func() سيكون في الواقع (pyobj.func)() .

إعادة كتابة a.foo(x) كـ foo(a, x) لن تحل مشكلة PyCall ، لأن foo ليس ولا يمكن أن يكون طريقة جوليا ، إنه شيء أحتاج إلى البحث عنه ديناميكيًا في وقت التشغيل . أحتاج إلى إعادة كتابة a.foo(x) كـ getfield(a, Field{:foo})(x) أو ما شابه [أو ربما getfield(a, Field{:foo}, x) ] حتى يتمكن getfield{S}(::PyObject, ::Type{Field{S}}) فعل الشيء الصحيح.

JeffBezanson https://github.com/JuliaLang/julia/issues/1974#issuecomment -38837755

بدأت أرى هنا الحاجة إلى عامل آخر ، لكن a..b ليس مقنعًا تمامًا. الحاجة إلى شخصيتين تبدو غاية ... الدرجة الثانية

أود أن أقول أنه ، من ناحية أخرى ، يتم كتابة .. بسرعة أكبر من $ أو @ أو | حيث لا يلزم الضغط على مفتاح Shift ، وأثناء كونه حرفين ، يظل الإصبع على نفس المفتاح: ابتسم:

stevengj آه ، فهمت. لكن وجهة نظري لا تزال قائمة ، وهي أن إعادة الكتابة يمكن أن تتم باستخدام وحدة ماكرو.

بالنسبة إلى JavaCall ، أحتاج فقط بشكل أساسي إلى معالج unknownProperty. أنا لا أحتاج في الواقع إلى إعادة كتابة أو اعتراض خاصية موجودة للقراءة أو الكتابة. فهل ستساعد القاعدة التي تقول "تتم إعادة كتابة الفأس إلى getfield (a ،: x) فقط عندما لا تكون x خاصية موجودة" في الحفاظ على عقلانية الأشياء؟

simonbyrne ، فإن طلب ماكرو من شأنه أن يقضي على الرغبة في الاتصال بين اللغات بشكل واضح وشفاف. أيضًا ، سيكون من الصعب جعلها تعمل بشكل موثوق. على سبيل المثال ، افترض أن لديك type Foo; p::PyObject; end ، ولكائن f::Foo تريد أن تفعل foo.p.bar حيث bar هو بحث عن خاصية Python. من الصعب تخيل ماكرو يمكنه التمييز بشكل موثوق بين معاني النقطتين في foo.p.bar .

بصراحة ، لا أرى أهمية كبيرة في الأسلوب. ستقلد الحزم عالية الجودة نمط Base وحزم أخرى حيثما أمكن ، وسيكتب بعض الأشخاص كودًا غريبًا بغض النظر عما نفعله. إذا وضعنا التحميل الزائد للنقاط في قسم لاحق من الدليل ، ونوصي باستخدامه فقط في عدد قليل من الحالات المختارة بعناية (مثل إمكانية التشغيل البيني بين اللغات ، وخصائص القراءة / الكتابة ، ربما لتجنب تلوث مساحة الأسماء لأشياء مثل factor.U ، وبصفة عامة كبديل أكثر نظافة لـ foo[:bar] ) ، فلا أعتقد أننا سوف نتجاوز الحزم باستخدام النقطة لكل شيء. الشيء الرئيسي هو أن نقرر ما الذي _نحن_ سنستخدمه ونوصي بهذا ، وربما يجب أن نحتفظ بقائمة الاستخدامات الموصى بها قصيرة جدًا ونوسعها فقط عند ظهور احتياجات العالم الحقيقي.

نحن لا نضيف صيغة فائقة السهولة مثل OO مثل type Foo; bar(...) = ....; end لـ foo.bar(...) ، لذلك سيحد ذلك من إغراء المبتدئين أيضًا.

أنا في اتفاق كامل مع stevengj هنا. أحب a..b للوصول إلى الحقل الحقيقي لأنه

  1. يبدو مشابهًا لـ a.b
  2. أقل ملاءمة ، كما ينبغي أن يكون
  3. هو فقط أقل ملاءمة _ قليلاً_
  4. ليس له معنى موجود ولم نعثر على أي استخدام مقنع له منذ أكثر من عام
  5. ليس غريبًا جدًا مثل a b`

مع هذا التغيير وربما (https://github.com/JuliaLang/julia/issues/2403) هل سيكون كل بناء جوليا تقريبًا محملاً بشكل زائد؟ (العامل الثلاثي هو الاستثناء الوحيد الذي يمكنني التفكير فيه) يبدو أن كل بناء الجملة تقريبًا يتم تخفيضه إلى أسلوب الإرسال الزائد هو ميزة موحدة جدًا بالنسبة لي.

أوافق على أنه نوع من التبسيط. المشغل الثلاثي و && و || يتحكمان في التدفق حقًا ، لذلك هذا نوع مختلف. بالطبع هذا النوع من الحجج ضد جعل a..b حق الوصول الحقيقي منذ ذلك الحين _that_ سيكون الصيغة الوحيدة غير القابلة للتحميل الزائد. لكن ما زلت أعتقد أنها فكرة جيدة. التناسق أمر جيد ولكنه ليس بالغ الأهمية في حد ذاته.

أوه ، هناك أيضًا استدعاء وظيفي غير مفرط التحميل. بسيط جدا لقد نسيت ذلك.

هذا ما يعالج المشكلة رقم 2403.

نعم. لكن هذا أقرب بكثير إلى الحدوث من ذلك.

الشيء الوحيد في المرهم بالنسبة لي هنا هو أنه سيكون من الجيد حقًا استخدام مشغل الوصول إلى المجال الحقيقي للوحدات النمطية ، لكن هذا لن يحدث على الأرجح لأن لا أحد يريد كتابة Package..foo .

إكمال التبويب بعد النقاط يصبح قبيحًا بعض الشيء ؛ من الناحية الفنية ، يجب عليك التحقق من الطريقة التي قد تستدعيها x. لمعرفة ما إذا كان من المناسب إدراج أسماء حقول الكائنات أو أسماء الوحدات. وآمل ألا يحاول أحد تحديد getfield(::Module, ...) .

أعتقد أن إكمال علامة التبويب يمكن أن يتم على النحو التالي: يسرد foo.<tab> "الحقول العامة" و foo..<tab> يسرد "الحقول الخاصة". بالنسبة للوحدات النمطية ، هل سيكون من الجيد السماح فقط بالتنفيذ الافتراضي لـ Mod.foo يكون Mod..foo وإخبار الأشخاص بعدم إضافة أساليب getfield إلى Module ؟ أعني ، يمكنك بالفعل إعادة تعريف إضافة عدد صحيح في اللغة - كل الجحيم ينهار وتحصل على segfault لكننا لا نحاول منعه. هذا لا يمكن أن يكون أسوأ من ذلك ، أليس كذلك؟

إنه في الواقع أسوأ قليلاً من ذلك ، لأن لغة البرمجة تهتم حقًا فقط بالتسمية. حل الأسماء أهم بكثير من إضافة أعداد صحيحة.

ليس لدينا الكثير من الخيارات إلا أن يكون لدينا Mod.foo افتراضيًا إلى Mod..foo ، ولكن ربما يتعين علينا استخدام Mod..foo للتمهيد في بعض الأماكن. عامل التشغيل .. مفيد للغاية هنا ، لأنه بدونه لا يمكنك حتى استدعاء Core.getfield أجل تحديد الاحتياطي. باستخدامه ، من المحتمل أن نزيل Core.getfield ولن يكون لدينا سوى .. .

هذه نقطة عادلة - التسمية هي نوع من الصفقة الكبيرة في البرمجة :-). يبدو أنه طريقة جيدة للذهاب - فقط .. وليس Core.getfield .

هاتان الفكرتان ،

[...] ضع نقطة التحميل الزائد في قسم لاحق من الدليل ، ووصي باستخدامه فقط في حالات قليلة مختارة بعناية https://github.com/JuliaLang/julia/issues/1974#issuecomment -38847340

و

[...] يجب أن يكون التفضيل هو استخدام بنية x.property بقدر الإمكان StefanKarpinski https://github.com/JuliaLang/julia/issues/1974#issuecomment -38694885

يعارضون بوضوح.

أعتقد أنه إذا تم اختيار الفكرة الأولى ، فإن مجرد إنشاء مشغل جديد .. لتلك "الحالات المختارة بعناية" سيكون أكثر منطقية.
كميزة ، فإن استخدام ..name للحالات التي يتم فيها استخدام [:name] حاليًا (DataFrames ، Dict {Symbol، ...}) سيكون أكثر سهولة في الكتابة / بناء الجملة مع الإشارة بوضوح إلى أن شيئًا مختلفًا عن الوصول إلى الحقل كان يحدث. علاوة على ذلك ، يمكن النظر إلى النقطة المزدوجة في ..name على أنها نقطتان مستدارتان ، وهي تلميح إلى بناء جملة الرمز :name ، ولن تكون هناك أيضًا مشكلة في إكمال علامة التبويب.
كعيوب ، الاستخدامات في PyCall et al. لن تكون قريبة جدًا من الصيغ الأصلية (وقد تكون مربكة للحالات التي يجب فيها استخدام . حقًا). لكن لنكن صادقين ، لن تكون جوليا متوافقة تمامًا مع بناء جملة Python ، وستكون هناك دائمًا حالات يتعين على المرء فيها كتابة الكثير في Julia باستخدام PyCall لتنفيذ تعليمات بسيطة بخلاف ذلك في Python. يمكن أن يوفر .. لمحاكاة . توازنًا جيدًا هنا. (من فضلك لا تفهموني خطأ ، أنا حقًا أحب PyCall وأعتقد أنها ميزة مهمة تستحق عناية خاصة)

الأيديولوجية الثانية ، التي أفضلها حاليًا ، لها القرار الكبير حول وقت استخدام property(x) أو x.property ، الأمر الذي يتطلب تعريفًا أنيقًا وواضحًا ، إذا كان هذا الشيء موجودًا .. .
يبدو أنه إذا كان الناس يريدون تحميلًا زائدًا . فذلك لأنهم يفضلون x.property نمط API في المقام الأول.
على أي حال ، أفضل أن أرى . ليس كمشغل وصول مفرط التحميل ولكن كمعامل وصول "خاصية" مفرط التحميل ( getprop(a, Field{:foo}) ربما؟) والذي يتم تعيينه افتراضيًا على عامل تشغيل حقل غير قابل للحمل الزائد .. .
يجب أيضًا اتخاذ قرارات أخرى ، على سبيل المثال ، التي سيتم استخدامها في رمز التنفيذ الملموس للوصول إلى الحقل ، أو .. أو . ؟ على سبيل المثال ، بالنسبة لمثال خطوة النطاقات ، أيهما سيكون اصطلاحيًا؟ step(r::Range1) = one(r..start) أو step(r::Range1) = one(r.start) ؟ (ناهيك عن السؤال عما إذا كان step يجب أن يكون طريقة أو خاصية).

لهذا السبب تراجعت عن تلك الزاوية واقترحت هذه المعايير: https://github.com/JuliaLang/julia/issues/1974#issuecomment -38812139.

مجرد فكرة واحدة ظهرت في رأسي أثناء قراءة هذا الموضوع المثير للاهتمام. يمكن استخدام التصدير للإعلان عن الحقول العامة ، بينما تكون جميع الحقول مرئية داخل وحدة التعريف ، على سبيل المثال:

module Foo
   type Person
     name
     age
   end
   export Person, Person.name
   <strong i="6">@property</strong> Person :age(person) = person..age + 1
end

في هذه الحالة ، لا يزال الشخص المُصدَّر يبدو مثل "الاسم" و "العمر" إلا في هذه الحالة يتم قراءة العمر فقط من خلال دالة تضيف واحدًا. قد يتم تصدير كل الأشخاص كشخص تصدير. * أو ما شابه.

[باو: اقتباسات]

emeseles يرجى توخي الحذر عند استخدام backticks لاقتباس أشياء تشبه كود Julia - فهذا يضمن الحفاظ على التنسيق ، ويمنع وحدات ماكرو Julia من إنشاء إشعارات GitHub للمستخدمين المشابهين.

. و .. محيران: فالتقدير الواضح والسهل التذكر شيء جيد

أنا أتطلع حقًا إلى أن أكون قادرًا على القيام بذلك. هل هذا تغيير كبير بما يكفي لوضع علامة عليه (أو العمل قيد التقدم في رقم 5848) كمشروع 0.4؟

نعم ، إنه بالتأكيد مشروع.

أعتقد أن معظمنا يتفق على أن الاستخدامات الموصى بها يجب أن تكون محدودة ، على الأقل في البداية. شعوري هو أنه يجب التوصية به في البداية لاستخدامين فقط: إمكانية التشغيل البيني (مع لغات أخرى ، كما في PyCall ، وبشكل عام للمكتبات الخارجية حيث يكون تدوين النقاط أمرًا طبيعيًا) ، وربما للكائنات ذات الحالة المتغيرة (منذ get_foo(x) و set_foo!(x, val) قبيحتان).

حتى لو أوصينا به فقط لإمكانية التشغيل البيني للمكالمات الأجنبية ، فإن هذا الغرض وحده يكفي لتبرير هذه الميزة في رأيي. بالنسبة للغة جديدة مثل Julia ، فإن التحدث بسلاسة مع بقية عالم البرامج أمر بالغ الأهمية.

ستيفن ، لست متأكدًا بنسبة 100٪ من أداة التجميع / المُحضر لأنني أخشى أن يؤدي ذلك قريبًا إلى تناقضات ولكنني أتفق مع حالة الاستخدام الأخرى. على رأس ذلك لدينا خصائص ديناميكية في Gtk.jl والتي من شأنها أن تستفيد أيضًا من بناء الجملة. المفضل الشخصي لدي هو تطبيق التعداد الذي أوضحه ستيفان في # 5842.

صدم. ما الذي يعيق التقدم في هذه القضية؟ هل هناك حاجة لاتخاذ قرار ، أم أن هذه المشكلة تعتمد على تغييرات داخلية أخرى ، لم يتم تنفيذها بعد ، أم أنها مجرد ترميز؟

ما الذي يعيق التقدم في هذه القضية؟

شخص ما يقوم بالعمل وبعض التردد حول ما إذا كان هذا هو الشيء الصحيح الذي يجب القيام به.

لاحظ أن ihnorton قد أجرى بالفعل مسودة تنفيذ مبكرة في # 5848. أعتقد أن العمل قد توقف في المقام الأول لأن هناك حاجة إلى بيان واضح من فريق جوليا الأساسي حول ما إذا كانت هذه ميزة مرغوبة.

أنا على متن هذا. JeffBezanson يبدو أنه على الحياد.

بالنسبة لي ، فإن امتلاك هذه الميزة سيجعل الانتقال من قاعدة شفرة Python الكبيرة إلى Julia أسهل. لشرح الطلاب ، إذا كانوا يستخدمون كود Python ، فإنهم يحتاجون إلى بناء جملة مختلف تمامًا ثم اعتادوا على ذلك ، وقد يصبح هذا صعبًا.

لقد أجرينا هذه المناقشة أعلاه في هذا الموضوع وما زلت لا أرى اتفاقًا كاملاً. يعتقد العديد من الأشخاص حاليًا أن واجهة برمجة التطبيقات العامة تتكون من وظائف / طرق بينما واجهة برمجة التطبيقات الخاصة هي حقول من النوع المركب. أستطيع أن أرى استثناءات نادرة جدًا من هذا المخطط. ( .U في تحليل LU؟)

هذا لا يعني أنني ضد هذا لأن الوصول إلى Python والتعدادات هي حالات يكون فيها هذا مفيدًا. لا يزال بإمكان المرء أن يتساءل عن مدى إلحاح الحاجة هنا وما إذا كان من الحكمة دفع هذا الأمر في نهاية دورة التطوير.

@ ufechner7 ، أوافق على أن الدافع الرئيسي هو interop interop. tknopp ، لن نتوصل أبدًا إلى اتفاق بالإجماع على شيء كهذا. في النهاية يتعلق الأمر بما يقررهJeffBezanson و StefanKarpinski .

أعتقد أن الكثير من التردد ينبع مما أتخيل أنه قد يكون أسوأ كابوس لجيف:

module DotOrientedProgramming
  Base.getfield(x, ::Field{:size}) = size(x)
  Base.getfield(x, ::Field{:length}) = length(x)
  ⋮
end

سأكره هذا كثيرًا أيضًا - أي حزمة تقرر إساءة استخدامها بهذه الطريقة ستفرض إساءة استخدامها على جميع أنواع النظام ، بما في ذلك بلدي. هذه الميزة قوية للغاية وستغير طريقة كتابة جوليا. للأفضل و (ربما ، لكن لا نأمل) أسوأ.

نعم بالتأكيد ستيفن ، قد لا تكون صياغته صحيحة مني. النقطة التي أردت توضيحها هي أن هذا التغيير يمكن أن يكون له تأثير كبير في كيفية تطور اللغة. كما أن فكرة "الواجهة الرسمية" التي لدينا في قضية أخرى تؤثر أيضًا من خلال جعل . مفرط التحميل. لذا ، نعم ، يسمح JeffBezanson و StefanKarpinski بالقرار . لا يزال السؤال هو ما إذا كان القرار يجب أن ينفذ الآن ...

لما يستحقه الأمر ، أفضّل جعل جميع القواعد التركيبية تقريبًا محملة بشكل زائد ومن ثم الاعتماد على الثقافة لمقاومة الانهيار الشديد معها.

+1 . أنا أعتقد أن هناك الفلسفية (وربما العملية ...) التناظرية قوية ل call إثقال هنا. يحتاج الدليل إلى قسم بعنوان Don't do stupid stuff: we won't optimize that . (بالطبع ، التحميل الزائد call كان جزئيًا _لأسباب تتعلق بالأداء - لكنه مليء باحتمالية إساءة الاستخدام)

  • : 100: لذلك. أعتقد أن الثقافة يجب أن تكون دافعًا كافيًا لعدم إساءة استخدام هذا

بشكل عام ، أنا مؤيد. احتمالية التعرض لسوء المعاملة ليست مصدر قلقي الأكبر. بالنسبة لي المشاكل الكبيرة

  • البنية المقبولة للوصول إلى الحقل "الحقيقي". لا أحب a..b كثيرًا.
  • الوحدات. الأسماء المؤهلة مهمة للغاية. من الممكن التعبير عنهم بطريقة الإرسال ، ولكن هناك صعوبات عملية. أي أنك تحتاج إلى المرور بالعديد من مراحل المترجم (ربما حتى من خلال التضمين) فقط لتعرف أن لديك اسمًا مؤهلًا. هذا يجعل الحياة أكثر صعوبة لأي شخص أدوات الكتابة التي تستهلك ASTs. كما أنه يجعل من السهل جدًا التعامل مع هذه الحالة بشكل غير صحيح في مثل هذه الأدوات.

يمكن حل هذه المشكلات بضربة واحدة باستخدام نفس الصيغة لكليهما ، ولكن يكاد يكون من المستحيل تخيل استخدام أي شيء سوى . للوحدات النمطية في هذه المرحلة. _ داخليا_ سيكون هناك بالتأكيد بناء جملة تجريدي لمراجع الوحدة ؛ سيكون الأمر محبطًا إذا لم تكن هناك طريقة لطيفة لفضح ذلك.

سنتي على هذا السؤال: لماذا لا أستخدم : للأسماء المؤهلة؟ إنه قيد الاستخدام بالفعل لشيء مشابه:

import Base: call, show, size

هذا من شأنه أن يعطي شيئا مثل

module Foo
    module Bar
        f(x) = 3*x
    end
    const a = 42
end

<strong i="10">@assert</strong> Foo:a == 42

Foo:Bar:f(789)

أم أن استخداماتهم الكثيرة بالفعل للرمز : ؟ يبدو أن الرمز :: (نمط C ++) مطول جدًا بالنسبة لي.

إن الرمز : هو بالفعل الرمز الأكثر حملًا في جوليا ، لذلك لن يساعد ذلك ، أخشى.

هل يمكننا تبسيط مشكلة التسمية المؤهلة بجعل تحميل module.name غير زائد؟ نظرًا لأن ارتباطات الوحدة ثابتة ، فإن ذلك سيسمح لنا بالحفاظ على نفس الدلالات ولكن دائرة قصر كل المنطق العادي لعمليات البحث عن الاسم المؤهل بمجرد معرفة أن LHS a.b عبارة عن وحدة نمطية. أعتقد أنه من المعقول جدًا عدم السماح للأشخاص بتجاوز معنى البحث عن اسم في الوحدة.

أنا أفضل بناء جملة a..b للوصول إلى الحقل الحقيقي. ما هو اعتراضك عليها؟

جانبا: أتمنى لو أننا استخدمنا ( ) لقوائم الاستيراد مثل بعض اللغات الوظيفية. بمعنى آخر:

import Base (call, show, size)

السبب هو أنه يمكننا جعل الفواصل اختيارية والسماح بفواصل لاحقة. يزعجني حقًا أن جميع الأسماء المستوردة تحتاج إلى فواصل لاحقة باستثناء الأخير الذي لا يمكن أن يحتوي على واحدة.

نعم ، كنت على وشك أن أذكر إمكانية جعل a.b يعني "إذا كان a وحدة نمطية ، فابحث عن الوحدة أولاً". قد يساعد ذلك ، ونحن بالتأكيد لا نريد تجاوز معنى البحث عن الوحدة. ومع ذلك ، فإنه يحتوي على بعض التعقيد ، حيث لا يمكننا بعد ذلك تمثيل a.b أنه الاستدعاء getfield(a,:b) . يجب أن تكون عقدة AST خاصة ذات فرع ضمني. بالطبع يمكننا استخدام فرع _explicit_ ، لكنني سأقلق بشأن سخام AST من ذلك.

لا يبدو أن هناك طريقة سهلة للخروج من مثل هذا الصراع الضخم بين احتياجات الواجهة الأمامية والخلفية.

إذا كان أي شخص آخر يحب a..b أعتقد أنه يمكنني تعلم كيفية التعايش معه. يبدو لي أنه يعني شيئًا مختلفًا تمامًا ، ربما فترة.

أنا لا أحب a..b أيضًا ولكن أتساءل لماذا سيكون مطلوبًا على الإطلاق. عند قراءة هذا الموضوع ، يحصل المرء على انطباع بأن التحميل الزائد سيتم استخدامه فقط في أغلفة اللغة وحالات الاستخدام الديناميكية حيث لا يلزم الوصول إلى الحقل الحقيقي.

لأنه في مرحلة ما تحتاج إلى الوصول إلى تمثيل كائن لفعل أي شيء به. يمكن للمرء أن يجادل بأن هذا سيكون نادرًا نسبيًا ، وبالتالي يمكن أن يكون قبيحًا مثل get_actual_field(a,:x) ، لكن يبدو أن هذه العملية مهمة جدًا بحيث لا تحتوي على بناء جملة.

أرى ذلك ولكن هذا يبدو وكأننا نسعى إلى بناء جملة لا نريد أن يستخدمه أحد بشكل صحيح؟

قد يكون عدم تقديم .. طريقة لقول "نعم" لحالات الاستخدام الديناميكي ولكن لا بالنسبة للبرمجة الموجهة بالنقاط

لا أرى كيف سيمنع ذلك البرمجة الموجهة بالنقاط ؛ لا يزال بإمكانك فعل

في حين أن بناء الجملة a..b يبدو وكأنه فاصل زمني (لقد استخدمته على هذا النحو) ، لا أعتقد أن حساب الفاصل يحتاج إلى صيغة الإدخال الخاصة به - كتابة Interval(a,b) هو مجرد حسنًا وليس هناك أي شيء آخر يريد أي شخص استخدام هذا النحو من أجله ، نظرًا لأنه كان عامل تشغيل في Julia لسنوات حتى الآن ولا أحد يستخدمه في الكثير من أي شيء. يبدو أيضًا أنه نوع من الوصول إلى الحقل.

أحد الجوانب الفضية لذلك هو أنه يمكننا استبدال module_name البغيض بـ m..name . عدم القدرة على الوصول إلى حقول كائنات الوحدة كان ثؤلولًا.

نعم ، كنت على وشك أن أذكر إمكانية جعل a.b يعني "إذا كان a وحدة نمطية ، فابحث عن الوحدة أولاً". قد يساعد ذلك ، ونحن بالتأكيد لا نريد تجاوز معنى البحث عن الوحدة. ومع ذلك ، فإنه يحتوي على بعض التعقيد ، حيث لا يمكننا بعد ذلك تمثيل a.b أنه الاستدعاء getfield(a,:b) . يجب أن تكون عقدة AST خاصة ذات فرع ضمني. بالطبع يمكننا استخدام فرع _explicit_ ، لكنني سأقلق بشأن سخام AST من ذلك.

هل يمكننا التعامل مع هذا بجعل a.b يعني getfield(a,:b) a.b دون قيد أو شرط ثم جعله خطأ لإضافة طرق إلى getfield التي تتقاطع مع طريقة getfield(::Module, ::Field) ؟ إنها نوعًا ما طريقة غريبة لفرض هذا السلوك ، لكن سيكون لها نفس التأثير في النهاية. عندئذٍ ، يمكن أن يستخدم التخفيض فقط تلك الحقيقة المتمثلة في أننا نعلم أنه لا يمكنك فعل ذلك للغش وخفض module.name للبحث عن اسم مؤهل.

حسنًا ، أصرح بالعكس: هل سيستخدم أي شخص في هذا الموضوع .. وإذا كانت الإجابة بنعم ، فما هي حالة الاستخدام النموذجية؟ (على سبيل المثال ، قد يكون التعتيم التام على الوصول إلى المجال الداخلي على ما يرام)

StefanKarpinski نعم ، قد ينجح ذلك. يمكن أن تكون حالة أخرى حيث نريد نوعًا من الأساليب "المختومة".

tknopp الوصول إلى module..name و module..parent :) أيضًا ، فقط للتوضيح ، هل تؤيد بناء جملة استدعاء الوظائف مثل get(obj,:field) للوصول إلى الحقول منخفضة المستوى؟

لا أنا لا أدعو إلى بناء جملة معين. أعتقد أنه سيكون من الجيد التأكد من سبب الحاجة إلى هذه الميزة وما هي حالات الاستخدام. بالنسبة لحالات الاستخدام الديناميكي ، فلا بأس بذلك

  • a.b هو حق الوصول إذا لم يتم تعريف Base.getfield(a, ::Field{:b})
  • a.b هو الإصدار الديناميكي إذا تم تعريف Base.getfield(a, ::Field{:b}) . في هذه الحالة ، يمكن أن يكون الوصول إلى المجال الحقيقي مظللًا

كان سؤالي هو ما إذا كانت هناك حالات استخدام لا يكون فيها التظليل جيدًا.

نعم؛ قد ترغب في تعريف pyobject.x بحيث يتم دائمًا البحث عن x في قاموس pyobject ، لجميع x . ثم يلزم وجود آلية منفصلة للوصول إلى حقول جوليا الخاصة بالجسم.

آه ، إذن كل شيء أو لا شيء؟ لقد حصلت بطريقة ما على انطباع يمكن أن يكون لدى المرء

type A
  c
end

Base.getfield(a::A, ::Field{:b}) = 3

a = A(1)

a.c # This still calls the field access
a.b # This calls the function

نعم ، يمكنك فعل ذلك ، ولكن لن تفعل كل الكائنات. سيرغب البعض في تعريف getfield(a::A, ::Field) لاعتراض كل الحقول.

طيب شكرا الآن حصلت عليه. ستحتاج جميع حالات الاستخدام الديناميكي إلى getfield(a::A, ::Field) وبالتالي تحتاج إلى أي طريقة لاستدعاء الحقول الداخلية.

ثم رأيي هو أن Core.getfield كافٍ ما لم يجد شخص ما حالة استخدام عملية يكون فيها هذا مزعجًا.

من المحتمل أن يكون هذا معطى ، لكننا سنسمح أيضًا بتجاوز setfield! ، أليس كذلك؟ أود حقًا عرض طرق العرض القابلة للتغيير في قاعدة بيانات حيث تصبح الصفوف أنواعًا.

نعم ، كان هذا انطباعي.

حسنًا ، IMHO سواء استخدام .. للوصول إلى الحقل الحقيقي أو Core.getfield ليس بهذه الأهمية. يمكن للمرء تقديم الميزة العامة على أنها تجريبية وجعل هذا الموضوع للتغيير.

السؤال هو ما إذا كان هذا سيتناسب مع الإطار الزمني 0.4 أم لا. لذلك # 5848 قريب من التنفيذ النهائي والوحدة النمطية قابلة للحل؟

johnmyleswhite : setfield! . في Gtk.jl سنستخدم كليهما.

لا يبدو واضحًا ما هي القاعدة عند استخدام هذه الميزة ومتى لا يتم استخدامها. أرى نقطة PyCall ، حيث يجب البحث عن طريقة / حقل ديناميكيًا ، وبالتالي لا يمكن أن تكون طريقة جوليا / نوع مركب (والصياغة الناتجة أقرب إلى Python). ولكن بعد ذلك ، لماذا تستخدمه لـ Gtk.jl؟ إذا بدأ في عمل foo.bar = x بدلاً من setbar!(foo, x) ، فإن كود Julia القياسي سيبدأ في استخدام هذا النمط أيضًا: هل هذا ما نريده؟ ربما يكون الأمر كذلك ، لكن لنكن واضحين بشأن ذلك.

هل سيكون من المقبول / الموصى به استخدام هذه الميزة لتنفيذ أدوات الحصول على الخصائص والمحددات المحددة للأنواع المجردة (والملموسة أيضًا)؟
أعتقد أن ذلك سيسمح بتجنب تضارب الأسماء في الأساليب المستخدمة للحصول على خصائص من أنواع مختلفة من الوحدات النمطية المختلفة.

المرجع: https://github.com/JuliaLang/julia/issues/4345 ، https://groups.google.com/forum/#!msg/julia -users / p5-lVNlDC8U / 6PYcvvsg29UJ

nalimilan : Gtk لديها نظام خصائص ديناميكي لا يتعلق بالحاصل / الواضعين.

tknopp آه ، حسنًا ، حقًا. ولكن بالنسبة لمعظم الخصائص الشائعة ، لديك وظيفة getter / setter (سريعة) ، بالإضافة إلى الخاصية الديناميكية. هل توصي باستخدام دالة getter / setter عند توفرها ، واستخدام صيغة التحميل الزائد للحقل للخصائص التي لا تحتوي على واحدة فقط؟ يبدو الأمر جيدًا بالنسبة لي - ولكن من الجيد أن يكون لديك سياسة واضحة حول IMHO.

من وجهة نظري في هذه المرحلة (وأعتقد أننا بحاجة إلى تجربة هذا قليلاً لمعرفة القواعد الصحيحة) ، يكون f(x) أفضل عندما يكون f منطقيًا كمفهوم عام مستقل مثل " length "بينما يجب استخدام x.f عندما لا يكون f مستقلًا عن x . لمحاولة ملاءمة المثال السابق في ذلك ، ليس من المفيد حقًا أن يكون لديك وظيفة step نظرًا لأن معظم المتجهات والمجموعات ليس لديها أي نوع من فكرة الخطوة - إنه _ فقط_ يكون منطقيًا عندما يكون لديك نطاق من نوع. وبالتالي ، لا بأس أن يكون x.step هو السبيل للحصول على خطوة النطاق x . إنها دعوة للحكم ، لكني أعتقد أن الحياة مليئة بهؤلاء.

لا أحب .. لأنه لا يمنحني إمكانية الوصول المباشر. ماذا عن foo.bar. النقطة الإضافية في النهاية تثبت أنها وصول مباشر.

يمكن أيضًا اختيار رمز يونيكود: لا يزال لدينا الكثير من هؤلاء المتبقيين ...

GlenHertz ، هذا لا يعمل حقًا إذا كان عليك

simonbyrne ، أنا عمومًا ضد وجود أي شيء في اللغة الأساسية أو مكتبة قياسية تتطلب استخدام Unicode. السماح له شيء ، وإجبار الناس على استخدامه شيء آخر تمامًا.

من وجهة نظري في هذه المرحلة (وأعتقد أننا بحاجة إلى تجربة هذا قليلًا لمعرفة القواعد الصحيحة) ، تكون f (x) أفضل عندما تكون f منطقية كمفهوم عام مستقل مثل "الطول" بينما يجب استخدام xf عندما تكون f غير مستقلة حقًا عن x.

ستكون قاعدتي الشخصية لاستخدام هذه الميزة هي: استخدم هذا فقط للتداخل اللغوي أو للأشياء التي تكون إما "حقولًا تقريبًا" أو "حقولًا مُعزَّزة". على سبيل المثال ، قد أستخدم هذا لتحديث ذاكرة تخزين مؤقت تعتمد على قيمة جميع الحقول في نوع ما.

سؤال واحد كبير لدي حول هذه الميزة: كيف يتفاعل هذا مع الاستدلال بالنوع؟ يبدو أنك على وشك تحديد دالة getfield(x::T, s::Symbol) تنتج مخرجات مكتوبة بشكل مختلف لقيم مختلفة من s . هل هذا يعمل فقط لأن getfield سحري؟ هل يمكنك إعادة تعريف ناتج getfield(x, s) للثابت x و s في أي وقت في البرنامج؟ إذا كان الأمر كذلك ، فكيف يتشابه ذلك مع عدم القدرة على إعادة تعريف النوع؟

يبدو أنك على وشك تحديد دالة getfield(x::T, s::Symbol) تنتج مخرجات مكتوبة بشكل مختلف لقيم مختلفة من s .

هذا هو سبب الخطة للتعبير عن هذا كـ getfield{s}(x::T, f::Field{s}) حيث s هو رمز.

لقد فاتني ذلك. شكرا لتوجيهي.

nalimilan : نعم ، سيتم استخدام الحقول المحملة بشكل زائد فقط للخصائص الديناميكية. هذه هي الطريقة التي يريد جيمسون التعامل معها وأعتقد أن هذا أمر جيد. يتم إنشاء جميع عناصر التعيين والمحددات الحقيقية تلقائيًا ولكنها لا تزال تعمل بدون كل تسمية get / set. البث المباشر في الوحدة النمطية GAccessor (باختصار G_ )

في بناء الجملة ، لماذا لا تستخدم <- للوصول الحقيقي للحقل؟
إنه مشابه لـ -> في c ++ والذي يتم استخدامه في lamdas ولكن <- غير مستخدم حاليًا.
يمكن قراءتها من النوع والحصول على القيمة مباشرة.

ستترك .. غير مستخدمة لأولئك الذين يرغبون في استخدامها على فترات ثابتة وستستخدم زوجًا غير مستخدم ليس له استخدامات أخرى يمكنني التفكير فيها حتى الآن.

دعونا لا نستخدم تدوين إسناد R للوصول إلى الحقل.

يمكننا استخدام -> لعكس C / C ++ مباشرة والحصول على صيغة جديدة لـ
وظائف مجهولة. لم أهتم كثيرًا بالوظيفة المجهولة
بناء الجملة لأنه مقتضب قليلاً / غير قابل للقراءة. ربما يمكننا أن نفعل بدلا من ذلك
شيء مثل

func (x) x ^ 2 end

أو الأطول والأكثر اتساقًا

الوظيفة (x) x ^ 2 end

ربما تكون هناك طريقة للتوصل إلى صيغة جيدة لا تتطلب ذلك
باستخدام النهاية.

عدم تغيير المناقشة كثيرًا ، لكن سيكون ذلك منطقيًا بالتأكيد
لاستخدامها -> للوصول إلى الميدان الحقيقي.

يوم الأربعاء ، 28 كانون الثاني (يناير) 2015 ، الساعة 8:49 صباحًا ، John Myles White [email protected]
كتب:

دعونا لا نستخدم تدوين إسناد R للوصول إلى الحقل.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/1974#issuecomment -71857083.

quinnj : func (x) x^2 end يعمل بالفعل. لكن من الجيد أن يكون لديك صياغة موجزة جدًا للوظائف المجهولة: map(x->x^2, 1:10)

لا أعتقد أن الوصول إلى الحقل يحتاج إلى بناء جملة خاص (الحرف الموحد كما اقترح simonbyrne على ما يرام كما هو الحال في الخيار). لا أريد أن أخسر x -> x^2 .

يبدو أن هذه المشكلة لا تزال مفتوحة / معلقة المناقشة؟ كان من المثير للاهتمام قراءة جميع التعليقات المختلفة هنا حول عامل التشغيل النقطي.

هل كانت هناك أي اقتراحات لإضافة رموز مميزة أخرى للمشغل؟ قد يكون استخدام شيء مثل :> بديلاً جيدًا. لها أوجه تشابه مع |> وقد يكون لها جوليا الأصلية _feel_:

c = foo.a + foo.b
pyobj:>obj:>process(c)

بينما لا تزال الكتابة أسهل بكثير من:

pyobj[:obj][:procees](c)

أو المقارنة:

someobj :> array |> length 
# vs
length(get_array(someobj)) 

أنا جديد في جوليا ، لكنني اكتسبت بسرعة تقديراً قوياً لنهج الإرسال المتعدد. البرمجة الموجهة للكائنات - خاصة للبرمجة العلمية - تجعل الكثير من المهام أكثر تعقيدًا. سأكون قلقًا من أن نموذج OO / بناء الجملة سيؤثر سلبًا على تطور أسلوب Julia.

أو بدلاً من ذلك ، نظرًا لأنني نسيت أمر التدرب على السلسلة و / أو الاقتباس:

someobj <: field_name |> length

elcritch ، يتم استخدام <: حاليًا لأن Julia "هو نوع فرعي من عامل" ، وإذا تم تقديم :> فمن المحتمل أننا سنرغب في استخدامه لشيء متعلق بالنوع بسبب ذلك التراث.

إذا كان استخدام instance..member يمثل مشكلة ، فإليك بعض الاحتمالات. احمي عينيك! من المحتمل أن يكون كل واحد من هؤلاء أسوأ:

  • instance^.member (نقطة جزرة)
  • instance~.member (نقطة تيلدا)
  • instance:.member (نقطتان نقطتان)
  • instance*.member (نقطة نجمة)
  • instance-.member (نقطة شرطة)
  • [email protected] (نقطة عند تسجيل الدخول)
  • instance&.member (نقطة أمبير)
  • instance$.member (نقطة دولار)
  • instance<.>member (نقطة سفينة الفضاء)

أعتقد بصدق أن (أ) .. يبدو جيدًا بما فيه الكفاية و (ب) لا يهم حقًا ما إذا كان يبدو جيدًا لأن هذا سيكون دائمًا ركنًا غامضًا من اللغة. سيستخدم معظم الأشخاص instance.member لأنهم سيكون لديهم فقط حقل أو طريقة getfield ، لكن ليس كلاهما.

(بالنسبة لهذه المسألة ، فإن معظم الأشخاص الذين يرغبون في استخدام كلٍّ من العضو والطريقة لن يكلفوا أنفسهم عناء التعرف على .. . سيحددون طريقة لـ foo.member ويطلقون على "field foo._member . يمكن القول إن هذا أسلوب أفضل على أي حال - فهذا يعني أنه عندما تقرأ تعريف type ، سيتضح على الفور أن _member ليس من المفترض أن يكون شيئًا يمكنك أو يجب عليك الوصول إليه مباشرةً. قد يكون هذا حجة لجعل .. شيئًا قبيحًا وغامضًا مثل :. بدلاً من أخذ عقارات ترقيم قيمة.)

سأفتقد القدرة على استخدام .. كعامل تشغيل للفاصل الزمني ، لكن الوصول الزائد إلى الحقل هو مقايضة جديرة بالاهتمام. على الرغم من أنني متردد في الخوف من إضافة المزيد من المعاني إلى القولون ، إلا أن :. لا يبدو بهذا السوء.

لاحظ أن :. هو في الواقع بناء صالح لـ symbol(".") الوقت الحالي ، لذلك قد لا يكون من الجيد استخدام ذلك. النقطة التي من المحتمل أن تكون .. مفيدة قد تم أخذها جيدًا ؛ لا ينبغي أن نضيعه على بناء جملة لا يكاد أي شخص يستخدمه. سأكون سعيدًا تمامًا لاستخدام شيء أقبح مثل @. (نظرًا لأن . ليس اسم ماكرو صالحًا ولا يمكن أن يبدأ معرّفًا ، فلا يبدو أن هذا يتعارض مع أي شيء ). مرة أخرى ، ستكون هذه ركنًا غامضًا من جوليا لدرجة أنه لا يستحق محاولة جعلها جميلة.

+1 لإنجاز ذلك باستخدام .. وتجاهل أي قبح محتمل

نعم ، دعنا نذهب إلى .. أي حال إذا كان من الممكن استخدام .. ثم أعتقد أنه سيكون منشئ _range_ ، لكن مهلا هناك بالفعل مع النقطتين على سبيل المثال. start:stop .

ركلة أخيرة: ماذا عن .: ؟ هل هو دقيق للغاية أن يكون لديك ab ، a. (b) ، a. (: b) _and_ a.:b؟

hayd ، يبدو هذا دقيقًا جدًا وسهل الاستخدام عن طريق الصدفة.

ihnorton ، هل هناك أي فرصة لإحياء نسخة من # 5848؟ يمكننا طرح السؤال النحوي واستخدام Core.getfield(x, Field{y}) للوصول إلى الحقل "الحقيقي".

تم ركوب الدراجة حول بناء الجملة Core.getfield جانباً ، فهل هناك أي أسئلة جوهرية متبقية؟

في # 5848 ، اقترح tknopp فقط جعل الوصول إلى المجال "الحقيقي" مفرط التحميل ، على عكس اقتراح JeffBezanson بأن كل شيء يجب أن يكون مفرط التحميل. شخصيًا ، سأكون سعيدًا بجعل من المستحيل تحميل حقول حقيقية بشكل زائد ، باستثناء أن الطبيعة الديناميكية للغة ستجعل على الأرجح ذلك أكثر تعقيدًا في التنفيذ. على سبيل المثال ، باستخدام نهج "كل شيء قابل للحمل الزائد" ، إذا كان لديك x::Vector{Any} ، فيمكن تفسير تنفيذ getfield(x[i], Field{:y}) x[i].y getfield(x[i], Field{:y}) وسيقوم نظام الإرسال بالشيء الصحيح بغض النظر عما إذا كان y هو حقل حقيقي ، بينما إذا كنت تريد فقط استدعاء getfield للحقول "الافتراضية" ، فسيتعين على برنامج الترميز تنفيذ مجموعة فرعية مصغرة من نظام الإرسال لفحص وقت التشغيل لـ x[i] نوع

كان السؤال الآخر هو ما إذا كان يجب زيادة التحميل على Module.foo . من ناحية ، هناك تناسق معين لاستخدام getfield لكل شيء ، والمثال المذكور أعلاه Vector{Any} يمكن أن يحتوي على أعضاء مصفوفة Module لذلك علينا التعامل مع هذه الحالة على أي حال. من ناحية أخرى ، أشار JeffBezanson إلى أن هذا قد يجعل التجميع أكثر صعوبة ، ويجعل سلوك الإعلانات مثل function Base.sum(...) صعبًا. أفضّل أن أجعل Module.foo غير قابل للتحميل الزائد ، على الأقل في الوقت الحالي ، في أي حالة يعرف فيها المترجم أنه يعمل مع Module (أي ليس Vector{Any} ) ؛ يبدو أن التناقض الطفيف يستحق العناء من أجل أن تكون متحفظًا بشأن ما يتم تغييره.

+1 لعدم السماح بزيادة التحميل على Module.foo .

للتناغم هنا ، أحد مجالات الحوسبة العلمية حيث تكون برمجة OO وبناء الجملة في الواقع متفوقة على FP هي النمذجة القائمة على الوكيل. على الرغم من أنني أفتقد الميراث الملموس والمتعدد لإعداد التسلسلات الهرمية للوكيل ، إلا أن التجريد الخفيف والسريع والنماذج الأولية السريعة لجوليا مذهلة - لقد ظهر بالفعل زوجان من أطر عمل ABM.

في ABM ، يُفضل تدوين النقطة للتعبير عن تفاعلات الوكيل: Agent1.dosomething (Agent2) مقابل dosomething (Agent1، Agent2).

هذا واضح ليس أكبر حالة استخدام ، ولكن سيكون من الجيد الاحتفاظ بهذا السكر النحوي للتفكير والترميز حول ABMs.

أود أيضًا أن يكون هذا النحو متاحًا في Julia. مثل
بقدر ما أقدر النهج الموجه للوظيفة من التصميم
منظور ، طريقة استدعاء طريقة مفيدة جدا ويمكن قراءتها في عدة
المجالات. سيكون رائعًا إذا كان Ab (C) يعادل b (A ، C).
في 22 أبريل 2015 8:50 صباحًا ، كتب "datnamer" [email protected] :

للتناغم هنا ، أحد مجالات الحوسبة العلمية حيث برمجة OO
وبناء الجملة هو في الواقع متفوق على FP هو النمذجة القائمة على الوكيل. على الرغم من أنني
تفوت الميراث الملموس والمتعدد لإنشاء التسلسلات الهرمية للوكيل ، فإن
خفيفة الوزن وسريعة التجريدات والنماذج الأولية السريعة لجوليا
مذهل - ظهر بالفعل عدد من أطر عمل ABM.

في ABM ، يفضل استخدام تدوين النقطة للتعبير عن تفاعلات الوكيل:
Agent1.dosomething (Agent2) مقابل الشيء (Agent1، Agent2).

من الواضح أن هذه ليست حالة الاستخدام الأكبر ، ولكن سيكون من الجيد الاحتفاظ بها
السكر النحوي للتفكير والترميز حول ABMs.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/1974#issuecomment -95218555.

في ABM ، يُفضل تدوين النقطة للتعبير عن تفاعلات الوكيل: Agent1.dosomething (Agent2) مقابل dosomething (Agent1، Agent2).

لماذا هذا أفضل؟ تحرير: أعني في سياق ABM هذا على وجه التحديد.

من فضلك ، دعونا لا ننغمس في الحروب الدينية بسبب التهجئة. @ dbeach24 ، لا أحد يقترح أن يكون a.b(c) يعادل في جوليا b(a,c) ؛ هذا لن يحدث.

النقاط الزائدة ضرورية للتفاعل الطبيعي مع اللغات الأخرى. هذا سبب كاف.

Subject.Verb (DirectObject)

أمر طبيعي إلى حد ما في عدة سياقات. يستخدم الكثير من مبرمجي OO ل
هو ، وبينما هو مجرد إعادة ترتيب للوظيفة (أ ، ب) ، فإن هذا إعادة الترتيب
يفعل الكثير لسهولة القراءة ، IMO.
في 22 أبريل 2015 10:32 صباحًا ، كتب "آندي هايدن" [email protected] :

في ABM ، يفضل استخدام تدوين النقطة للتعبير عن تفاعلات الوكيل:
Agent1.dosomething (Agent2) مقابل الشيء (Agent1، Agent2).

لماذا هذا أفضل؟

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/1974#issuecomment -95256390.

كنت أقترحه. (آسف ، لم أقصد بدء حرب ولا أعرف
الاقتراح لن يحظى بشعبية.) اعتقدت أنني رأيت هذا يأتي من قبل
في المنتديات ، لكنه لم يدرك أنه قد تم رفضه بالفعل باعتباره a
فكرة سيئة. هل لي بالسؤال لماذا؟ (هل يمكنك توجيهي إلى موضوع؟)

شكر.
في 22 نيسان (أبريل) 2015 ، الساعة 11:09 صباحًا ، "Steven G. Johnson" [email protected]
كتب:

من فضلك ، دعونا لا ننغمس في الحروب الدينية بسبب التهجئة. @ dbeach24
https://github.com/dbeach24 ، لا أحد يقترح أن يكون ab (c)
مكافئ في جوليا إلى ب (أ ، ج) ؛ هذا لن يحدث.

تعتبر النقاط الزائدة أمرًا ضروريًا للتفاعل السلس مع اللغات الأخرى.
هذا سبب كاف.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/JuliaLang/julia/issues/1974#issuecomment -95266671.

أحد أسباب عدم القيام بذلك هو أن a.b يبحث عن b في نطاق a ، بينما b وحده يبحث عن b في النطاق المرفق. سيكون الأمر محيرًا للغاية إذا كان الوصول المنقط لا يبحث أحيانًا في كائن الجانب الأيسر.

راجع للشغل ، تعتبر ميزة لا يتم البحث عن الوظائف في Julia داخل الكائنات ولكن في النطاق الحالي. أعتقد أن الخوف من أن يبدأ الناس في استخدام الوظائف التي يتم البحث عنها داخل الأشياء هو أحد الأسباب التي أدت إلى تأخير التحميل الزائد للنقطة.

toivoh ، أي تنفيذ @ dbeach24 ، السبب الأساسي لعدم تشجيع الاستخدام العشوائي a.b(c) هو أنه إذا كان لديك عدد كبير جدًا من التركيبات للقيام بنفس الشيء ، فإن اللغة والمكتبات تتحول إلى فوضى. من الأفضل اختيار تهجئة واحدة والالتزام بها ، ويفضل إرسال جوليا المتعدد b(a,c) لأنه من الواضح أن b ليس "مملوكًا" لـ a - b(a,c) يتم تحديد طريقة a و c .

الاستثناء الأكبر ، بالطبع ، هو استدعاء المكتبات الخارجية بلغات مثل Python أو C ++ ، حيث من الجيد أن تكون قادرًا على عكس بناء الجملة للمكتبة التي تتصل بها. (بحيث يمكن للأشخاص على سبيل المثال ترجمة الوثائق والأمثلة مباشرة إلى جوليا دون تغيير الكثير.)

هل أنا مبلل بالكامل ، لكن لا يعني ab (arg) أخذ دالة مجهولة مخزنة في الحقل b من a ، ثم تقييمها باستخدام الوسيطة المعطاة؟

مرسل من الايفون الخاص بي

في 22 نيسان (أبريل) 2015 ، الساعة 5:06 مساءً ، كتب ستيفن ج. جونسون [email protected] :

خارجي

ScottPJones هذا يعمل حاليًا بشكل جيد ، لكنه لا يعتبر أسلوبًا جيدًا بشكل عام.

لم أكن مهتمًا بالأسلوب أم لا ، لقد اعتقدت فقط أنه نظرًا لأنه يحتوي بالفعل على معنى ، فهذا يتوافق مع الطريقة التي تعمل بها جوليا (أي القدرة على تخزين وظائف مجهولة في الحقول) ، فقد كانت حجة جيدة _ لا حاول معاملة ab (arg) كما لو كانت b (a، arg).
قد يكون لدي استخدام لامتلاك بنية (نوع) مع أعضاء يقومون بتخزين وظائف مجهولة ، حيث أقوم بتحميل وظائف مكتوبة في Julia من قاعدة بيانات ، ثم أقوم بتحليلها ، وتخزين الوظائف في كائن ...
ما هو الأسلوب "جوليان" الأفضل لفعل شيء من هذا القبيل؟

شكر!

ScottPJones أعتقد أن هناك اتفاقًا لا ينبغي أن تكون مكافئة *.

يمكن أن تكون هناك استثناءات لقاعدة "النمط" ، ولكن يجب أن تكون هناك حالة مقنعة لاستخدام دالة في الحقل ، مثل التحميل الزائد للنقاط. أعتقد أن المشكلة تكمن في أنه لا ينبغي للناس أن يفعلوا ذلك بمحض إرادتهم / من أجل ذلك / لأنهم يستطيعون ذلك.

قد يكون هذا مثالاً ، ولكن قد تكون هناك أيضًا طريقة أفضل (بالتأكيد ليست الطريقة الوحيدة) ...

99٪ + من الأفضل الإرسال على typeof (a) ؛ لا توجد حقول وظيفية ، ولا تحميل زائد للنقطة.

* _ ومع ذلك ، أعتقد أن الجميع يعرف أنه سيكون هناك حزمة تقوم بذلك بالضبط ...

في D لديهم حتى اسم "بنية استدعاء دالة موحدة" مقابل a.b(arg) وهو شائع جدًا ، لكنني أعتقد أنه يتعارض بشدة مع الوظيفة العامة ، طريقة الإرسال المتعددة التي تعمل جوليا. إذا كانت الوظائف المعنية مجهولة المصدر أو مطبوعة تمامًا ، فأعتقد أن الأشياء ستنجح ، لكن هذا مقيد جدًا في IMO. لا أعتقد أن هناك سببًا كبيرًا لتخزين حقول الوظائف داخل نوع مركب ، باستثناء العادة من لغات OO التقليدية القائمة على الفصل. أفضل مكان لتخزين الوظائف العامة إذا كنت تقوم بتحميلها من مكان ما سيكون في وحدات.

لكننا ابتعدنا كثيرًا عن "الأسئلة الموضوعية" الآن. أنا أيضًا أؤيد أن أكون متحفظًا بشأن كيفية السماح بالحمل الزائد على getfield ، وعدم السماح بزيادة التحميل على الوحدات النمطية ، وعدم القلق كثيرًا بشأن البنية الخاصة لـ "getfield حقيقي".

stevengj : نعم ، وكما كنت أحاول أن أقول ، هذا هو أحد الأسباب الأساسية لعدم حدوث أن يصبح a.b(c) يساوي b(a, c) ، بغض النظر عما نفعله مع زيادة التحميل على النقاط بخلاف ذلك .

كان هناك بعض النقاش حول هذا الموضوع في القائمة البريدية. من وجهة نظري ، فإن المشاركة الأكثر صلة (بواسطةnalimilan) لهذا الموضوع هي: https://groups.google.com/d/msg/julia-users/yC-sw9ykZwM/-607E_FPtl0J

إضافة إلى تعليق johnmyleswhite فيما يتعلق بالسياسة الشخصية حول وقت استخدام هذه الميزة - يبدو لي أن بعض أفكار HTTP يمكن أن تكون مفيدة هنا ، وأن getfield() يجب ألا يكون له آثار جانبية و setfield!() يجب أن تكون غير فعالة (أي أن تسميتها عدة مرات بنفس القيمة يجب أن يكون لها نفس تأثير تسميتها مرة واحدة). ليس بالضرورة قواعد صارمة وسريعة يتم فرضها من قبل المترجم ، ولكن إرشادات الاستخدام لمنع الأشياء من الجنون.

لقد قمت بنشر حل بديل باستخدام الأنواع البارامترية مع معلمات المؤشر والتحويل لاستدعاء أداة ضبط مخصصة عند تعيين حقل:
آخر: https://groups.google.com/forum/#!topic/julia -users / _I0VosEGa8o
الكود: https://github.com/barche/CppWrapper/blob/master/test/property.jl

أنا أتساءل عما إذا كان يجب علي استخدام هذا النهج في الحزمة الخاصة بي كحل بديل حتى setfield! التحميل الزائد متاح ، أم أنه الكثير من الضغط على نظام النوع البارامتري؟

أود أن أذكر ميزة إضافية واحدة وهي زيادة التحميل على getfield / setfield! ، آمل أن يكون هذا هو المكان المناسب لذلك ، أنا آسف بخلاف ذلك. (ظهر موضوع ذي صلة على https://groups.google.com/forum/#!topic/julia-users/ThQyCUgWb_Q)

جوليا مع جيتفيلد / سيتفيلد! التحميل الزائد سيسمح بتنفيذ أنيق بشكل مدهش لوظيفة التحميل التلقائي في حزمة خارجية. (شاهد كل العمل الشاق الذي كان يجب وضعه في ملحق التحميل التلقائي IPython https://ipython.org/ipython-doc/3/config/extensions/autoreload.html للحصول على هذه الوظيفة.) فكرة التحميل التلقائي هي يمكن تعديل الوظائف والأنواع في الوحدات الخارجية أثناء العمل مع REPL.

TLDR: التحميل الزائد getfield / setfield! ، يجب أن تقوم القواميس وحزمة مشابهة لـ https://github.com/malmaud/Autoreload.jl بتنفيذ الحيلة.


لكي تكون أكثر تحديدًا ، تخيل حزمة مشابهة لـ Autoreload.jl تقوم بما يلي.

تقوم أولاً بإنشاء وحدة نمطية M.jl:

module M
type Foo
  field1::Int64
end
bar(x::Foo) = x.field1 + 1.0
end

في REPL ، تكتب

julia> using Autoreload2
julia> arequire("M")
julia> foo = Foo(42)

ثم تقوم بتغيير M.jl إلى

module M
type Foo
  field1::Int64
  field2::Float64
end
bar(x::Foo) = x.field1+x.field2

هذا من شأنه أن يتم تحميله تلقائيًا وتحويله إلى

# type redefinition removed as already done by Autoreload.jl
const field2_dict = Dict{UInt64,Float64}()
setfield!(x::Foo, ::Field{:field2}, value) = field2_dict[object_id(x)] = value
getfield(x::Foo, ::Field{:field2}) = field2_dict[object_id(x)]
<strong i="25">@do_not_inline</strong> bar(x::Foo) = x.field1 + x.field2

ثم في REPL يمكنك القيام به

julia> foo.field2 = 3.14
julia> println(bar(foo)) # prints 45.14

لن يكون الأداء أسوأ مما هو عليه مع Python ، لذلك لن يفقد الأشخاص الذين يقومون بترحيل سير العمل الخاص بهم من التحميل التلقائي IPython أي شيء من حيث الأداء. وبمجرد إعادة تشغيل REPL ، ستعود إلى الأداء الكامل.

لقد تعبت من كتابة a[:field][:field2][:morestuff](b[:random_stuff]) لأنه غير مقروء حقًا. لذلك كتبت هذا الماكرو الصغير الذي يعمل مع حالات الاستخدام الخاصة بي في 0.4 و 0.5
https://github.com/sneusse/DotOverload.jl

TL ؛ DR
ماكرو يقوم بتحويل AST للتعبير a.b -> getMember(a, :b)

تمت الإزالة من 0.6 ، نظرًا لعدم وجود إجماع على أن هذه فكرة جيدة وهناك اقتراح متضارب بشأن ما يجب فعله مع بناء جملة النقاط.

@ كينو : هل لديك رابط للاقتراح المتضارب؟

لا تعتقد أن StefanKarpinski قد كتبه حتى الآن ، لكني أتوقع أن يكون هناك Julep حوله قريبًا.

لقد وجدت object.fieldname أجمل من وظائف getter مثل fieldname(object) أو get_fieldname(object) . ربما يكون object.fieldname (أو object$fieldname ) مكالمة إلى getpublicfield (ربما باسم أفضل) و object..fieldname هو getfield الفعلي (خاص) يمكن أن يكون خيارًا جيدًا. بهذه الطريقة ، يجب أن تحدد الأنواع getpublicfield بدلاً من الحاصل ، ومحاولة القيام بـ object.fieldname يجب أن تعطي معرف خطأ الحقل خاص (سيكون خاصًا إذا لم يكن لديه تعريف لـ getpublicfield ).

أضفت تسمية القرار. لقد نوقشت هذه المسألة باستفاضة وإما يجب القيام بها أم لا. عند قراءة ل# 5848 يبدو أنJeffBezansonStefanKarpinski وstevengj تريد هذا. إذا كانت الإجابة بنعم ، فيجب أن تحصل هذه المشكلة على علامة فارقة حتى لا تُنسى. وإلا أغلق. على أي حال ، أعتقد أن هذا تغيير يجب إجراؤه قبل الإصدار 1.0.

JeffBezanson وأنا Module (والذي سيتم التعامل معه بشكل خاص) ؛ (3) لا تقدم أي صيغة خاصة لـ Core.getfield (نظرًا لعدم وجود حاجة ملحة لوجود حمل زائد getfield ليكون له نفس اسم الحقل "الحقيقي" ؛ يمكن أن يبدأ الأخير بـ شرطة سفلية).

stevengj : a.fieldname(b) أيضًا؟ سيؤدي هذا إلى استنتاج المناقشة أعلاه. علاوة على ذلك ، سيكون من الرائع وضع تسمية مناسبة لهذا الحدث (1.0؟). شكر!

جيف وأنا لم نناقش قضية الحجج المتعددة. شعوري هو أننا قد ندعمها أيضًا ، حيث يمكنك محاكاتها على أي حال من خلال إعادة دالة من حالة عدم الجدال (ولكن ليس من المهم القيام بها على الفور لنفس السبب).

أستخدم محولًا لإلقاء القيم والتحقق من صحة البيانات.
مثله:

abstract AbstractAge{T}
abstract AbstractPerson
type PersonAge <: AbstractAge{AbstractPerson} 
    value::Int64
end

Base.convert(t::Type{AbstractAge{AbstractPerson}}, value::Int64) =  begin
  if value < 140 && value > 0
    PersonAge(value) 
  else
     throw(ErrorException("ValueError"))
  end
end

type Person <: AbstractPerson
  age::AbstractAge{AbstractPerson}
end 

a = Person(32)
a.age = 67

إليك تنفيذ ممتع من 3 أسطر لهذا:

diff --git a/base/boot.jl b/base/boot.jl
index cd3ae8b..a58bb7e 100644
--- a/base/boot.jl
+++ b/base/boot.jl
@@ -266,6 +266,9 @@ Void() = nothing

 (::Type{Tuple{}})() = ()

+struct Field{name} end
+(::Field{f})(x) where {f} = getfield(x, f)
+
 struct VecElement{T}
     value::T
     VecElement{T}(value::T) where {T} = new(value) # disable converting constructor in Core
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index b4cb4b5..59c9762 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -1685,7 +1685,7 @@
     (if (and (pair? e) (eq? (car e) '|.|))
         (let ((f (cadr e)) (x (caddr e)))
           (if (or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$))
-              `(call (core getfield) ,f ,x)
+              `(call (new (call (core apply_type) (core Field) ,x)) ,f)
               (make-fuse f (cdr x))))
         (if (and (pair? e) (eq? (car e) 'call) (dotop? (cadr e)))
             (make-fuse (undotop (cadr e)) (cddr e))

تفكيري هو أن a.b يجب أن يستدعي بالفعل وظيفة الإسقاط Field{:b}() بدلاً من getfield ، بحيث تحصل على وظائف مثل x->x.a بالفعل مجانًا. يتيح ذلك أيضًا لـ getfield أن يعني دائمًا الوصول إلى الحقل ذي المستوى المنخفض.

يعمل التطبيق أعلاه بشكل كامل ولكنه صعب جدًا على المترجم (sysimg + 5٪ ، وهو نوع من المفاجأة السارة حقًا). لذلك سيحتاج هذا إلى بعض الاستدلالات التخصصية وتحتاج بعض التحسينات المبكرة إلى التحديث ، ولكن بعد ذلك نأمل أن يكون هذا قابلاً للتطبيق.

أنا مندهش من أن الاختبارات يمكن أن تمر بهذا التنفيذ. ألا يجعل هذا الدلالة من المستحيل على codegen تحسين مراجع الوحدة؟ يبدو أيضًا أنه سيجعل المتغيرات العالمية أكثر تكلفة (السرعة والذاكرة). لا يبدو أنه من المحتمل جدًا أن يظهر هذا في sysimg. على الرغم من أن تدهور الاستدلال يبدو أنه كان يجب أن يجعل sysimg أصغر هنا ، لذا فإن 5٪ أسوأ لا يبدو بداية جيدة)

نعم ، هناك رمز في jl_resolve_globals لتحويل هذه إلى GlobalRefs والتي تحتاج إلى تحديث. بخلاف ذلك ، يجب أن يتم تضمينها بحيث يكون من الممكن لـ codegen التعامل معها. في الاستدلال ، ربما نحتاج فقط إلى حالة خاصة مماثلة لتلك الخاصة بالمجموعة getindex .

ربما نحتاج فقط إلى حالة خاصة مماثلة لتلك الخاصة بـ tuple getindex

تأمل هذه الحالة الخاصة وتفترض أنه لن يتم تحديد أي طريقة تتقاطع مع توقيع الأسلوب getindex المدمج. لا أرى كيف تنطبق هذه الحالة بشكل خاص هنا.

أود إضافة طريقة لـ ::Module وأقول إنه غير مسموح لك بتظليلها - ربما يتم فرضها بخطأ فعلي.

JeffBezanson هل لديك فرع بهذه الأسطر الثلاثة؟ حاولت إضافتها بنفسي إلى مبنى محلي ، لكن يبدو أن جوليا قد تحركت الآن ولم أستطع تشغيلها.

يجب أن أقول إنه إذا كانت لدي رغبة واحدة فقط في ميزة في جوليا 1.0 ، فستكون هذه هي. سيحل مشكلتين طويلتين لدي في كل من Mimi و Query .

أعتقد أن حالة الاستعلام عامة جدًا. أعتقد أنه يمكن للمرء أن يكتب نسخة من NamedTuples مع هذا الذي لم يكن بحاجة إلى إنشاء أنواع جديدة في وحدات الماكرو ، وهذا بدوره NamedTuple مع مجموعة من الحقول التي هي محسوبة في دالة ولدت. أعتقد أن ذلك سيمكنني من كتابة إصدار مستقر من النوع blackrock / NamedTuples.jl # 4 ، وهو إلى حد بعيد أكبر حجر عثرة بالنسبة لي في Query.jl الآن.

باختصار ، سيكون هذا أمرًا رائعًا وذا قيمة فائقة لقصة معالجة البيانات بأكملها في جوليا.

هل الصيغة أدناه متاحة؟

function (obj::MyType).plus(n::Int)
       return obj.val + n
end

لماذا حقًا تريد هذا النحو؟

إن الرغبة في كتابة obj.plus(n) بدلاً من obj + n هي مشكلة خطيرة في متلازمة ستوكهولم.

حسنًا ، كان المثال المعطى تافهًا (وسيئًا).
كانت مجرد فكرة لاستخدام بناء الجملة هذا بدلاً من التحميل الزائد على getfield والقدرة على استخدام الوسائط.

أنا مهتم في الغالب بالوظيفة. يبدو أن وجود بناء جملة مختصر لزيادة التحميل على getfield أقل أهمية بكثير ولا يستحق التورط في الجدال حوله. علاوة على ذلك ، فإن getfield و setfield! يعكسان بشكل مباشر getindex و setindex! ولذا فهي طبيعية إلى حد ما في جوليا. أخيرًا ، لا يُعد الاستخدام المكثف لأسلوب OO مناسبًا حقًا لمصطلح Julia ، ولا أعتقد أننا نريد تشجيعه من خلال صيغة تعريف طريقة تشبه OO (لكن انظر تعليقي أعلاه بخصوص الحجج).

الشيء الوحيد الذي خطر لي هو أنه تم إهمال عامل التشغيل $ . الآن ، من الواضح أن هذا يجعل القيام بشيء مثل $(x, sym::Symbol) = ... متاحًا بالفعل ، ولكن يمكننا أيضًا الاستمتاع بإعادة كتابة نحوية مربي الحيوانات مثل:

x$y          => $(x, ::Type{Val{:y}})
x$z(args...) => $(x, ::Type{Val{:z}}, args...)

أعتقد أن هذا يغطي معظم الحالات المذكورة في هذه المشكلة بالفعل دون القيام بالحمل الزائد الكامل. بصراحة ، عامل التشغيل . مشبع لغويًا جدًا في Julia ، لذا فإن شيئًا كهذا يبدو أسهل في الهضم ومريح بما يكفي ليظل مفيدًا.

quinnj ، تم اقتراحه بالفعل في # 18696.

لأن لدينا بالفعل . للوصول إلى المجال، ومع ذلك، فإنه يبدو ائقة لاثنين من الحقل وصول مثل المشغلين واحدة overloadable واحد لا. وسيكون من غير الطبيعي بعض الشيء إجراء مكالمات بين اللغات إلى Python ولغات OO الأخرى ، والتي تستخدم تقريبًا . عالميًا.

لا أرى إمكانية التشغيل البيني مع اللغات الأخرى كحجة صالحة لتقديم شيء كهذا. إنه مثل القول ، "تبدو شفرة Python على هذا النحو ، حتى نتمكن من التظاهر بأننا Python ، يجب علينا القيام بذلك أيضًا." لم أرى حجة لهذا من شأنها أن تجعل جوليا نفسها أفضل و / أو أكثر اتساقًا. من المعروف بالفعل أن جوليا لا تقدم بناء جملة x.f() على غرار OOP ؛ السماح بأشياء من هذا القبيل يتطلب عدم اتساق.

stevengj ، جزء من المكان الذي أتيت منه على الرغم من حقيقة أن x.f _ ليس حقل وصول. لا يوجد عضو حقل فعلي f . تدور هذه المشكلة برمتها حول التحميل الزائد على getfield وأعتقد أن المخاوف الرئيسية هي الارتباك المحتمل حول ما إذا كان x.f يشير بالفعل إلى حقل أو يقوم بشيء آخر تحت الغطاء.

ميزة إعادة الكتابة النحوية التي اقترحتها هي أنها تفي بقصة تفاعل اللغة دون إدخال مزيد من الارتباك مع getfield ؛ هذا ما كنت أشير إليه عندما ذكرت أن . سيكون مشبعًا جدًا. هل سيكون x$f أكثر تعقيدًا؟ أنا فقط لا أفهم لماذا هذا _ has_ ​​لاستخدام عامل التشغيل النقطي.

تدور هذه المشكلة برمتها حول التحميل الزائد على getfield وأعتقد أن المخاوف الرئيسية هي الارتباك المحتمل حول ما إذا كان x.f يشير بالفعل إلى حقل أو يقوم بشيء آخر تحت الغطاء.

لا أعتقد أن هناك أي احتمال للارتباك في اقتراحJeffBezanson المكون من ثلاثة أسطر: يتم دائمًا تخفيض a.b في استدعاء دالة الإسقاط ، وليس استدعاء getfield . ثم هناك طريقة افتراضية / احتياطية في الأساس لوظيفة الإسقاط تستدعي getfield . يمكن للمستخدمين إضافة أساليب لأنواعهم الخاصة إلى وظيفة العرض هذه إذا أرادوا. يعني getfield دائمًا وصولًا منخفض المستوى إلى الحقل في هذا الاقتراح ، ولن يضيف المستخدمون طرقًا إلى getfield (أفترض أن هذا هو ما قصدته بعبارة "overloading getfield"). هذا يبدو نظيف جدا بالنسبة لي بعد قولي هذا ، ليس من الواضح بالنسبة لي ما إذا كان هذا الاقتراح لا يزال مطروحًا على الطاولة أم لا ، يبدو أن هناك بعض مخاوف المترجم التي لا أفهمها :)

أرغب حقًا في الحصول على هذه الميزة (لطالما أحببتها في Scala). الوصول إلى الحقول IMHO يأتي بشكل طبيعي جدًا في Julia (مقارنة ، على سبيل المثال ، طريقة Java في التحديد الدفاعي لأحجام ومحددات كل شيء). ولكن بدون القدرة على إضافة حقول "افتراضية" ، يصبح من الصعب جدًا تطوير / إعادة بناء الهياكل دون كسر الكثير من التعليمات البرمجية.

أعلم أن هذا قد تم وضع علامة عليه v2.0 ، لكني أود إعادة طرح هذا مرة أخرى على أمل إعادة النظر في هذا الإصدار 1.0. ستكون هذه الميزة ذات قيمة كبيرة لمطوري الحزم / المكتبة.

عند إنشاء حزمة للمستخدمين ، فإن التحميل الزائد على موصل السمة سيسمح لمشرفي الحزم بتقديم واجهة مستخدم أكثر وضوحًا. سأجادل في ذلك ،

complex_data_structure.attribute

من السهل كتابة من

get(complex_data_structure, :attribute)

حيث get دالة مطلوبة للحصول على البيانات الموصوفة بواسطة :attribute .

يمكن أن يؤدي ذلك أيضًا إلى تحسين قابلية الاكتشاف في REPL ، وسيفيد رمز اللغة واستكشاف البيانات.

بالإضافة إلى ذلك ، فإن أداة تقاطع سمة الواضع ستكون أيضًا ذات قيمة لا تصدق. خذ بعين الاعتبار المثال التالي (موجود بالفعل في العديد من البرامج النصية الخاصة بي حاليًا :)) ،

set(complex_data_structure, :attribute, modify_attribute(get(complex_data_structure, :attribute), additional_arguments))

إذا تم تضمين خاصية getter و setter كجزء من Julia ، فسيصبح ما سبق هو التالي.

complex_data_structure.attribute = modify_attribute(complex_data_structure.attribute, additional_arguments)

هذا في رأيي المتواضع أكثر قابلية للقراءة. (ملاحظة جانبية: يمكنني استخدام تركيب أنبوب لجعله أكثر قابلية للقراءة ، ولكن additional_arguments مرة أخرى سيعقد الأمر مرة أخرى. وستظل الحجة هنا قائمة.)

علاوة على ذلك ، فإن تقييد القيم التي يقدمها المستخدم هو حقًا حالة استخدام شائعة ، وسيكون هذا أمرًا رائعًا حقًا في الإصدار 1.0. سيحسن بشكل كبير واجهات المستخدم لحزم متعددة. حاليًا ، على حد علمي ، لا توجد طريقة للقيام بما يلي (هل يمكن لأحد أن يصححني إذا كنت مخطئًا)؟

module point

mutable struct Point
    x::Int
    y::Int
    function Point(x, y)
        if x < 0 || y < 0
            throw(error("Only non-negative values allowed"))
        end
        this = new(x, y)
    end
end

end
# point

p1 = point.Point(-1, 0)
# Only non-negative values allowed

# Stacktrace:
# [1] point.Point(::Int64, ::Int64) at ./In[30]:8
# [2] include_string(::String, ::String) at ./loading.jl:515

p1 = point.Point(0, 0);
p1.x = -1;
p1
# point.Point(-1, 0)

يمكن للمُنشئ أن يقيد مدخلات المجال ببنية غير قابلة للتغيير ، ومع ذلك قد يستمر المستخدم في إدخال قيم غير صالحة. قد تساعد أدوات تحديد السمات ومحددوها هنا ، لأنهم سيجعلون التعليقات على صلاحية البيانات هنا أكثر فورية ، وهذا سيجعل واجهة أكثر نظافة كمستخدم للغة.

سيفيد هذا أيضًا الحزم الأخرى بشكل كبير مثل PyCall.jl و DataFrames.jl لبناء واجهات أفضل وأكثر سهولة للمستخدمين. أعرب مؤلفو هذه الحزم أيضًا عن اهتمامهم أعلاه بالحصول على هذه الميزة.

أفكار؟ من خلال قراءة الموضوع ، يبدو أن هذا قريب جدًا بالفعل من النهاية. أنا فضولي ما هي أفكار المؤلفين حول هذا؟

تم تنفيذه في نوع ماكرو اختياري مستقر هنا: https://github.com/bramtayl/DotOverloading.jl. أعتقد أنه يحتوي على إمكانات Base.

bramtayl ، أعتقد أن الحاجة إلى وضع @overload_dots قبل تعبيرات a.b تهزم النقطة هنا.

لم أكن أقترح إضافة الماكرو إلى القاعدة ؛ كنت أقترح أن يتم دمج الإستراتيجية المستخدمة بواسطة الماكرو في المحلل اللغوي. ومع ذلك ، فهو ماكرو يمكن تشغيله على ملفات كاملة أو حتى اختراقه في IDE.

قد يستلزم ذلك تحليل a.b إلى Expr(:., :a, :(Val{:b}()) وخفضه إلى get_field_overloadable(a, Val{:b}())

bramtayl ، راجع تنفيذ Jeff

تتمثل إحدى مشكلات التحميل الزائد في getfield في أن بعض المكتبات لا تحتوي على واجهة معقولة للداخلية لهيكل البيانات. عندما يكون كل ما أريده هو تعديل نقطة بيانات في هيكل حتى أتمكن من تشغيل الكود الخاص بي وإعداد تقريري ليوم غد ، فأنا لا أتطلع بشكل خاص إلى تحرير الكود في مكتبة بثلاثة مستويات في عمق التبعية حتى أكون قادرًا للوصول مباشرة إلى نقطة البيانات بطريقة معقولة وسريعة. أريد أن أشعر أنني أتحكم في هياكل البيانات التي أستخدمها.

النقطة الثانية هي أنه عندما أستخدم getfield و setfield ، أريد توقعًا معقولًا بأنني أصل مباشرة إلى بنية البيانات بدلاً من بعض آليات الوظائف الضخمة. بالإضافة إلى ذلك ، يتم استخدام الكلمة الرئيسية struct لتحديد نوع ، لتذكيرك بـ C ، وأشعر أنها تمنحك توقعًا بأن الوصول إلى getfield يجب أن يكون مباشرًا.

لذلك ، أعتقد أن استخدام عامل التشغيل $ بدلاً من ذلك هو حل وسط معقول لأنه لا يوجد توقع أن يكون الوصول مباشرًا كما هو الحال في getfield ، فهو بالفعل شخصية خاصة في سياقات أخرى وبالتالي لن يكون مفاجئًا للغاية عندما يتم استخدامه بهذه الطريقة ، سيكون من السهل إهماله لأن قلة من الناس يستخدمونه ولأنه لن يكون وظيفة بعد الآن ، ويتم استخدامه بالمثل في R.

تتمثل إحدى مشكلات التحميل الزائد في getfield في أن بعض المكتبات لا تحتوي على واجهة معقولة للداخلية لهيكل البيانات.

تنفيذ JeffBezanson من الأعلى لا getfield (أو setfield ).

أود أيضًا أن أدافع عن هذا لجعله 1.0. غالبًا ما أجد نفسي ممزقًا بين كتابة الأحرف / الإعدادات للحفاظ على مرونة الكود الخاص بي إلى حد ما (ثم أتساءل عن كيفية تسميتها) ، أو "السماح / التشجيع" لمستخدم الكود الخاص بي لاستخدام الوصول المباشر إلى الحقل.

لا يبدو لي أن كتابة الكثير من الحاصلين والمستوطنين بشكل دفاعي في المقدمة - في النهاية ، ليس لدى Julia حقول خاصة / محمية ، لذا فهي تشجع المستخدم على الوصول إلى الحقول مباشرة. ثم هناك سؤال حول كيفية تسمية الكثير من وظائف getter- / setter دون المخاطرة بالكثير من التعارضات مع الحزم الأخرى. والبديل ، إضافة طرق لـ getfield و setfield! (أو ما شابه) ، يتم إرسالها على Val{:fieldname} أو نحو ذلك ، لا يبدو سهل الاستخدام أيضًا.

من ناحية أخرى ، إذا كان الوصول المباشر إلى الحقل يقفل بشكل أساسي جميع البنى إلى الأبد ، فمن الواضح أنه لا ينبغي تشجيعه - خاصة بالنسبة للكود طويل العمر. قد يبدو تطبيق JeffBezanson طريقة رائعة للخروج من هذه المعضلة.

صحيح ، davidanthoff. يجب أن أخلط بين التحميل الزائد لـ getfield والتحميل الزائد على بناء جملة الوصول إلى الحقل . . قصدت التحميل الزائد على بناء جملة الوصول إلى المجال.

هناك طرق متوافقة مع الإصدارات السابقة لإضافة هذه الميزة ، لذا يمكن إضافتها في إصدار 1.x ، لكنها لا تحدث في الإصدار 1.0. ليس لدينا تصميم نهائي أو وقت لتنفيذه حتى لو كان لدينا تصميم.

سيكون من الملائم للغاية استخدام بناء الجملة النقطي على مؤشرات البنى (C-).

قد يكون بناء الجملة المفضل لدي هو استخدام النقاط لتحريك وتحويل المؤشرات فقط ، واستخدام [] لـ deref.

لذا ، فإن البنية somepair a :: Int b :: Int end ، و p :: Ptr {somepair} ، ثم pa هي مؤشر للحقل ، وأكتب إليها مع pa [] = 3 ، أو اقرأ مع x = السلطة الفلسطينية [].

بعد ذلك ، نحتاج فقط إلى تقديم إعلانات عن الأنواع ، وربما طريقة لاستيراد رؤوس C ، ثم يصبح تغليف C أمرًا سهلاً.

ملاحظة ، للتوضيح ، شيء مثل:

function getfield(p::Ptr{T}, fn::Symbol) # dispatch on values of T and fieldname
ftype = fieldtype(T, fn)
offset = fieldoffset(T,fn)
return convert(Ptr{ftype}, p+offset)
end

getindex(p::Ptr{T}) where T = unsafe_load(p)
setindex!(p::Ptr{T}, v) where T = unsafe_store!(p, convert(T,v))

بالنسبة إلى نقاط المكافأة ، يمكن تصدير الأنواع من lib الخاص بوقت تشغيل julia ، ويمكن أن يعطينا pointer_from_objref مؤشرًا مكتوبًا بشكل جيد لمزيد من الاستبطان المريح.

لدي شعور بأن النقابات يجب أن تعمل بشكل تلقائي ، فقط من خلال امتلاك حقلين بنفس الإزاحة؟

chethega أعتقد أنك تبحث عن https://github.com/JuliaLang/julia/pull/21912 ، والذي يوفر نفس الميزة تقريبًا ، دون المشكلات المحيطة بتبني نموذج ذاكرة C (انتهاكات نوع العقاب ، خارج -الوصول ، والتسميات المستعارة للمؤشرات الداخلية ، وما إلى ذلك ، مما يحد من تحسينات الأداء الممكنة في تلك اللغة).

هل التكاثر المستمر يجعل هذا أكثر قابلية للتنفيذ؟

الرجاء تغيير معلم إلى 1.0! :)

@ Liso77 ماذا تقصد؟ تم تنفيذ هذا بالفعل على git master ، كما هو موضح في الحالة عند الإغلاق.

nalimilan آسف إذا فهمت ذلك خطأ! لكنني اعتقدت أن 1.x تم تصنيفها على أنها أشياء مؤجلة سيتم حلها بعد 1.0. وهذا حُل الآن ...

المصدر المفتوح هو مجتمع لامركزي. يحدد المعلم الأساسي ما يجب أن يكتمل بـ 1.0 ، لكن المساهمين والعمل على ما يريدون. في هذه الحالة ، أراد شخص ما هذا في الإصدار 1.0 ، لذلك ساهم في الكود للحصول عليه هناك.

@ Liso77 كما أفهمها ، لن يكون هذا في الإصدار 1.0. تم تعيين تاريخ تجميد ميزة Julia v1.0 على 15 ديسمبر ، ولكن تم إغلاق هذه المشكلة في 17 ديسمبر ، لذا أعتقد أنه يمكننا توقعها في إصدار 1.x. يمكن لمطوري Core تصحيح لي إذا كان تفسيراتي غير صحيحة.

لا ، تم دمجه في الإصدار الرئيسي وسيكون في الإصدار التالي.

:) حسنا! لقد اعتقدت للتو أنه من الجيد تسمية 1.0 ما يحدث في 1.0. إذا لم يكن مطلوبًا فأسف على الإزعاج! :)

أعتقد أن ملف NEWS هو طريقة أفضل لمعرفة ما يجري في 1.0.

تمت إضافة المعلم الرئيسي بمعنى "يمكن تنفيذه دون كسر التوافق في سلسلة إصدارات 1.x" ، ولكن بعد أن أصبح الرمز جاهزًا ، تم دمجه على أي حال قبل تجميد ميزة 1.0. لقد قمت بإزالة المعلم الرئيسي من أجل الوضوح ، ولكن في هذه المرحلة ، سيكون كل شيء مدمج في Master في 1.0.

شكرا على التوضيح! هذا محمس! كان ملف الأخبار أيضًا مفيدًا بشكل خاص.

شكرا للإزالة! أنا أيضًا سعيد جدًا لأنه سيأتي في الإصدار 1.0! :)

أتساءل عما إذا كانت هناك طريقة لدعم هذه "الحقول المعرفة ديناميكيًا" الجديدة في الإكمال التلقائي ، على سبيل المثال من خلال السماح بزيادة التحميل على fieldnames ؟. قد يكون هذا قويًا للغاية ، للاستخدام التفاعلي ، على سبيل المثال عند التعامل مع DataFrame s (بافتراض أنهم سيدعمون df.column_name في المستقبل) مع العديد من الأعمدة و / أو أسماء الأعمدة الطويلة.

أعتقد في الوقت الحالي أن REPL (توسيع الجدولة) ، IJulia ، إلخ. ننظر إلى تعريف النوع ، وليس المثيل؟ ولكن ربما يمكن تغيير ذلك ، للاستخدام التفاعلي. ربما يكون من المستحيل دعمه في IDE مثل Juno ، على الرغم من ذلك ، حيث لا تتوفر المثيلات أثناء الترميز.

oschulz ، يمكنك بالفعل زيادة التحميل على fieldnames :


julia> struct Foo; foo; end

julia> fieldnames(Foo)
1-element Array{Symbol,1}:
 :foo

julia> Base.fieldnames(::Type{Foo}) = [:bar, :baz]

julia> fieldnames(Foo)
2-element Array{Symbol,1}:
 :bar
 :baz

ويبدو أن fieldnames هو ما يبدو عليه REPL:

julia> x = Foo(3)
Foo(3)

julia> x.ba<tab>
bar baz

yurivish صحيح - ولكن هل القيام بذلك "آمن" حاليًا؟ لست متأكدًا مما يعتمد أيضًا على fieldnames .

إذا لم يكن آمنًا ، يجب أن يكون من الممكن تحديد complete_fieldnames(x) = fieldnames(x) ، واستخدام complete_fieldnames لإكمال REPL ، وزيادة التحميل للإكمالات المخصصة.

نعم ، هذا هو سبب طرح هذا الموضوع - في حالة الحاجة إلى تغيير / إضافة شيء ما في Base ، حتى يتمكن REPL والأصدقاء من الاستفادة منه لاحقًا. في ضوء ميزة 0.7 تجميد ...

لهذا السبب أنا سعيد لأننا أطلقنا على الوظيفة getproperty ؛ يساعد في توضيح أنه لا يشير إلى نفس الشيء مثل fieldnames . التدخل في fieldnames يمكن أن يسبب مشاكل خطيرة بالتأكيد.

قد نحتاج إلى propertynames مقابل لإعطاء قيم الخاصية الصالحة. بالطبع ، قد لا يكون هذا مفهومًا محددًا جيدًا ، لذلك ربما نريد شيئًا أكثر تحديدًا للإكمال.

كان لدي شعور بأن هذا قد يتطلب القليل من التحليل العميق والمدخلات من الخبراء (شكرًا!) - هل يجب أن نفتح عددًا جديدًا لهذا؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات