diff options
60 files changed, 7492 insertions, 2224 deletions
diff --git a/ar-ar/python3-ar.html.markdown b/ar-ar/python3-ar.html.markdown new file mode 100644 index 00000000..e1a12690 --- /dev/null +++ b/ar-ar/python3-ar.html.markdown @@ -0,0 +1,1019 @@ +--- +language: python3 +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] + - ["evuez", "http://github.com/evuez"] + - ["Rommel Martinez", "https://ebzzry.io"] + - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"] +translators: + - ["Ahmad Hegazy", "https://github.com/ahegazy"] +lang: ar-ar +filename: learnpython3-ar.py +--- + +لقد أُنشئت لغة البايثون بواسطة جايدو ڤان روسم في بداية التسعينات. هي الأن أحد أشهر اللغات الموجودة. +لقد أحببت لغة البايثون بسبب وضوحها. هي في الأساس عبارة عن سودوكود قابل للتنفيذ. + +ردود أفعالكم عن المقال مُقدرة بشدة. يمكنكم التواصل مع الكاتب الاساسي من خلال [@louiedinh](http://twitter.com/louiedinh) أو louiedinh [at] [google's email service] + +ملحوظة: هذا المقال يُطبق على بايثون 3 فقط. راجع المقال [هنا](http://learnxinyminutes.com/docs/python/) إذا أردت تعلم لغة البايثون نسخة 2.7 الأقدم + +```python + +# تعليق من سطر واحد يبدأ برمز الرقم. + +""" يمكن كتابة تعليق يتكون من أكثر من سطر + باستخدام ثلاثة علامات " + ، وعادة يُستخدم في كتابة التوثيقات. +""" + +#################################################### +## 1. أنواع البيانات البدائية والعمليات +#################################################### + +# لديك أرقام +3 # => 3 + +# العمليات الحسابية هي ما تتوقعه +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# نتائج قسمة الأرقام الصحيحية تُقرب للأصغر سواءًا كانت الأرقام موجبة أو سالبة. +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # يعمل في حالة الكسور أيضا +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# ناتج القسمة هو دائما كسر +10.0 / 3 # => 3.3333333333333335 + +# عملية باقي القسمة +7 % 3 # => 1 + +# الأُس (س ** ص، رفع س لقوى ص) +2**3 # => 8 + +# أفرض ترتيب العمليات الحسابية بالأقواس +(1 + 3) * 2 # => 8 + +# القيم الثنائية هي المعروفة عموما (ﻻحظ: تكبير أول حرف) +True +False + +# أنفي بـ (not) +not True # => False +not False # => True + +# العمليات على القيم الثنائية +# ﻻحظ ﻻيهم حالة الحرف (كبير أو صغير) في "and" و "or" +True and False # => False +False or True # => True + +# True و False هما في الواقع 1 و 0 لكن بمسميات مختلفة +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# عمليات المقارنة تنظر الي القيمة الرقمية لل True وال False +0 == False # => True +1 == True # => True +2 == True # => False +-5 != False # => True + +# عند استخدام المنطق الثنائي على القيم الصحيحة يتم تحويلهم الي قيم ثنائية لإجرات العمليات عليهم، لكن قيمهم الأصلية تعود +# ﻻ تخلط بين bool(قيمة صحيحة) و العمليات المنطقية الثناية and/or (&,|) +bool(0) # => False +bool(4) # => True +bool(-6) # => True +0 and 2 # => 0 +-5 or 0 # => -5 + +# مقارنة التساوي ب == +1 == 1 # => True +2 == 1 # => False + +# مقارنة الاختلاف ب != +1 != 1 # => False +2 != 1 # => True + +# مقارنات أخرى +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# لمعرفة هل القيمة في نطاق معين +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False + +# التسلسل يجعلها تبدو أجمل +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# (is مقابل ==) is تتحق من أن المتغيرين يشيران إلي نفس العنصر, +# لكن == تتحقق من أن العنصرين المُشار اليهما بالمتغيرين لهما نفس القيمة. +a = [1, 2, 3, 4] # اجعل a تشير إلي قائمة جديدة, [1, 2, 3, 4] +b = a # اجعل a تُشير الي ما تُشير إليه b +b is a # => True, a و b يُشيران إلي نفس العنصر +b == a # => True, قيمة عنصر a و b متساوية +b = [1, 2, 3, 4] # اجعل b تشير الي قائمة جديدة , [1, 2, 3, 4] +b is a # => False, a و b do ﻻ يشيران إلي نفس العنصر +b == a # => True, قيمة عنصر a و b متساوية + +# يمكنك إنشاء الكلمات (تسلسلات الحروف) عن طريق " أو ' +"This is a string." +'This is also a string.' + +# يمكنك جمع هذا النوع أيضا! لكن حاول ألا تفعل هذا. +"Hello " + "world!" # => "Hello world!" +# يمكنك الربط بين الكلمات بدون استخدام '+' (لكن ليس المتغيرات) +"Hello " "world!" # => "Hello world!" + +# يمكنك معاملة الكلمات كقائمة من الحروف +"This is a string"[0] # => 'T' + +# يمكنك معرفة طول الكلمة +len("This is a string") # => 16 + +# .format يمكنك استخدامها لبناء الجمل بشكل معين, مثل هذا: +"{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated" + +# يمكنك تكرار معاملات بناء الجملة لتقليل الكتابة. +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" + +# يمكنك استخدام الكلمات المفتاحية إذا لم تُرد العد. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna" + +# إذا كان كود بايثون 3 الخاص بك يحتاج لبايثون 2.5 أو نسخة أقدم +# يمكنك استخدام أسلوب بناء الجمل القديم: +"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way" + +# يمكنك أبضا بناء الجمل باستخدام f-strings أو حروف بناء الجمل (في بايثون 3.6 فما فوق) +name = "Reiko" +f"She said her name is {name}." # => "She said her name is Reiko" +# يمكنك ببساطة وضع أي كود بايثون داخل أقواس وستقوم بإخراج الجملة. +f"{name} is {len(name)} characters long." + + +# None عبارة عن كائن +None # => None + +# ﻻ تستخدم رمز المساواة "==" لمقارنة العناصر ب None +# استخدم is بدلا منه. يقوم بالتحقق من مساواة هوية العنصر +"etc" is None # => False +None is None # => True + +# None, 0, قوائم/جمل/قواميس/صفوف فارغة كلها تُترجم إلي False. +# كل القيم الأخرى True. +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False + +#################################################### +## 2. المتغيرات والمجموعات +#################################################### + +# بايثون لديها دالة عرض "print" +print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! + +# الافتراضي دالة print تطبع سطر جديد في النهاية. +# استخدم المعامل end لتغيير أخر الجملة المعروضة. +print("Hello, World", end="!") # => Hello, World! + +# طريقة بسيطة لطلب مدخل من الطرفية +input_string_var = input("Enter some data: ") # يقوم بإعادة البيانات ك "string" +# لاحظ: في النسخ القديمة من بايثون، دالة input() كان اسمها raw_input() + +# ﻻ يوجد تعريفات للمتغيرات، يتم تعيين قيمة المتغير مباشرة. +# العٌرف تسمية المتغيرات حروف_صغيرة_مع_خطوط_سُفلية +some_var = 5 +some_var # => 5 + +# محاولة استخدام متغير غير مُعين يعتبر خطأ +# إقرأ جزء 3.مسار التحكم لمعرفة المزيد عن التحكم في الأخطاء +some_unknown_var # يعرض خطأ NameError + +# يمكن استخدام if كتعبير واحد +# مساوِ للتعبير الأتي في لغة السي '?:' عملية ثلاثية +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# القوائم تحفظ المتسلسلات +li = [] +# يمكنك البدأ بقائمة مليئة +other_li = [4, 5, 6] + +# إضافة بيانات لأخر القائمة عن طريق append +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] +# حذف أخر عنصر في القائمة عن طريق pop +li.pop() # => 3 and li is now [1, 2, 4] +# هيا نعيده ثانية +li.append(3) # li is now [1, 2, 4, 3] again. + +# يمكنك الوصول لعناصر القائمة كما تفعل في ال array +# Access a list like you would any array +li[0] # => 1 +# للوصول لأخر عنصر +li[-1] # => 3 + +# محاولة الوصول لعنصر خارج نطاق القائمة يعتبر خطأ: IndexError +li[4] # يعرض خطأ IndexError + +# يمكنك النظر للنطاقات باستخدام تركيب التقطيع +# مؤشر/رقم/فهرس البداية مُضمن، مؤشر النهاية ﻻ +# (لمحبي الرياضيات هو نطاق مفتوح/مغلق) +li[1:3] # => [2, 4] +# إحذف أول عنصر ثم إعرض القائمة +li[2:] # => [4, 3] +# إحذف أخر عنصر ثم إعرض القائمة +li[:3] # => [1, 2, 4] +# حدد عنصر ثم إحذف الذي يليه ثم حدد عنصر وهكذا +li[::2] # =>[1, 4] +# اعرض نسخة معكوسة من القائمة +li[::-1] # => [3, 4, 2, 1] +# إستخدم أي تجميعة من الطرق المذكورة لعمل تقطيعات متقدمة +# li[start:end:step] + +# عمل نسخة من طبقة واحدة باستخدم التقطيع +li2 = li[:] # => li2 = [1, 2, 4, 3] لكن عند عمل(li2 is li) سينتج False. + +# إمسح أي عنصر من القائمة باستخدام "del" +del li[2] # li is now [1, 2, 3] + +# إمسح أول ظهور لقيمة. +li.remove(2) # li is now [1, 3] +li.remove(2) # يعرض خطأ ValueError لأن 2 غير موجود في القائمة + +# أضف عنصر في خانة معينة +li.insert(1, 2) # li is now [1, 2, 3] مرة أخرى + +# أحصل على مؤشر/رقم لأول ظهور للقيمة +li.index(2) # => 1 +li.index(4) # يعرض خطأ ValueError لأن 4 غير موجودة في القائمة + +# يمكنك جمع قوائم +# لاحظ: لا يتم تعديل قيمة li و other_li +li + other_li # => [1, 2, 3, 4, 5, 6] + +# إستخدم دالة "extend()" لربط القوائم +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# راجع وجود قيمة في القائمة باستخدام "in" +1 in li # => True + +# إحصل على طول القائمة باستخدام دالة "len()" +len(li) # => 6 + + +# الصفوف تشبه القوائم لكنها غير قابلة للتغيير. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # يعرض خطأ TypeError + +# لاحظ أن صف طوله عنصر واحد يحتاج لإضافة فاصلة "," بعد أخر عنصر +# لكن الصفوف من أي طول أخر، حتى صفر لا تحتاج. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# يمكنك عمل معظم عمليات القوائم على الصفوف. +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# يمكنك تفريغ الصفوف (أو القوائم) في متغيرات +a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 +# يمكنك أيضا عمل تفريغ واسع +a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4 +# الصفوف تُنشأ تلقائيا إذا تركت الأقواس +d, e, f = 4, 5, 6 # تم توسعة الصف 4, 5 ,6 في المتغيرات d, e, f +# بالترتيب حيث d = 4, e = 5 و f = 6 +# الأن إنظر إلي مدى سهولة التبديل بين قيم متغيرين +e, d = d, e # d is now 5 and e is now 4 + + +# القواميس تُخزن خرائط من المفتاح للقيمة +empty_dict = {} +# هذا قاموس مملوء +filled_dict = {"one": 1, "two": 2, "three": 3} + +# لاحظ أن القواميس يجب أن تكون أنواع غير قابلة للتغيير. +# هذا للتأكد من أن المفتاح يمكن تحويله لقيمة ثابتة للوصول السريع. +# الأنواع الغير قابلة للتغير تتضمن: الأرقام الصحيحة، الكسور، الكلمات، الصفوف. +invalid_dict = {[1,2,3]: "123"} # =>يعرض خطأ TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # القيم يمكن أن تكون من أي نوع. + +# يمكنك البحث عن قيمة باستخدام [] +filled_dict["one"] # => 1 + +# يمكنك الحصول على كل المفاتيح باستخدام "keys()". +# نحتاج لإرسالها لدالة list() لتحويلها لقائمة. سنتعلم هذا لاحقًا +# لاحظ - لنسخ بايثون قبل 3.7، ترتيب مفاتيح القاموس غير مضمون. نتائجك +# يمكن ألا تساوي المثال بالأسفل. مع ذلك، من أول بايثون 3.7، +# عناصر القاموس تحتفظ بالترتيب الذي تم إضافة المفاتيح به في القاموس. +list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+ + +# يمكنك الحصول على كل القيم باستخدام "values()". +# مرة أخرى نستخدم list() للحصول عليها كقائمة. +# نفس الكلام السابق بخصوص ترتيب المفاتيح +list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ + +# إفحص للتأكد من وجود مغتاح في القاموس باستخدام "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# البحث عن مفتاح غير موجود يعرض خطأ KeyError +filled_dict["four"] # KeyError + +# استخدم "get()" لتجنب الخطأ KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# دالة get تدعم إدخال قيمة افتراضية عند عدم وجود البحث +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# "setdefault()" تقوم بإدخال قيمة جديدة في القاموس في حالة عدم وجود المفتاح فقط. +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 + +# إضافة عنصر للقاموس +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # طريقة أخرى للإضافة + +# مسح المفاتيح من القاموس باستخدام del +del filled_dict["one"] # Removes the key "one" from filled dict + +# من بايثون 3.5 فما فوق يمكنك أيضا استخدام خيارات تفريغ إضافية +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + + +# المجموعات تُخزن .. مجموعات +empty_set = set() +# .تهيئة مجموعة بمجموعة قيم. نعم، تشبه قليلا تهيئة القاموس. أسف +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} + +# مثل مفتاح القاموس، عناصر المجموعة يجب أن تكون غير قابلة للتغيير. +invalid_set = {[1], 1} # => يعرض خطأ TypeError: unhashable type: 'list' +valid_set = {(1,), 1} + +# إضافة عنصر أخر للمجموعة +filled_set = some_set +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +# المجموعات لا يمكن أن تحتوي على عناصر مكررة +filled_set.add(5) # it remains as before {1, 2, 3, 4, 5} + +# تقاطع مجموعتين باستخدام & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# اتحاد مجموعتين باستخدام | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# الفرق بين مجموعتين باستخدام - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# الفروق بين مجموعتين باستخدام ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# لفحص هل المجموعة على اليسار مجموعة عُليا للمجموعة على اليمين (تحتوي على كل عناصرها) +{1, 2} >= {1, 2, 3} # => False + +# لفحص هل المجموعة على اليسار مجموعة فرعية من المجموعة على اليمين +{1, 2} <= {1, 2, 3} # => True + +# للتأكد من وجود عن في مجموعة استخدم in +2 in filled_set # => True +10 in filled_set # => False + + + +#################################################### +## 3. مسار التحكم والعمليات التكرارية #Control Flow and Iterables +#################################################### + +# هيا ننشيء متغير +some_var = 5 + +# الأن الأمر if. الفجوات (المسافات قبل الأوامر) مهمة في البايثون! +# العُرف استخدام أربع مسافات. ليس تبويب. +# هذا السطر البرمجي يطبع "some_var is smaller than 10" +if some_var > 10: + print("some_var is totally bigger than 10.") +elif some_var < 10: # This elif clause is optional. + print("some_var is smaller than 10.") +else: # This is optional too. + print("some_var is indeed 10.") + + +""" +For عبارة عن حلقات تدور حول عناصر قوائم +:ثم تطبع + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # يمكنك استخدام format() لترجمة كلمات بشكل معين. + print("{} is a mammal".format(animal)) + +""" +"range(number)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها +من الصفر إلي رقم معين +ثم يطبع: + 0 + 1 + 2 + 3 +""" + +for i in range(4): + print(i) + +""" +"range(lower, upper)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها من القيمة السُفلى +lower حتى القيمة العُليا upper +ثم يطبع: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +"range(lower, upper, step)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها من القيمة السُفلى +lower حتى القيمة العُليا upper، ثم يقوم بالزيادة قيمة الstep. +إذا لم تُحدد ال step, القيمة الأفتراضية 1. +ثم يطبع: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +While هي عبارة عن حلقات تدور حتى عدم تحقق شرط معين. +وتطبع: + 0 + 1 + 2 + 3 +""" +x = 0 for +while x < 4: + print(x) + x += 1 # اختصار ل x = x + 1 + +# يمكنك التحكم في الأخطاء والاستثناءات باستخدام مجموعة try/except +try: + # استخدم "raise" لرفع خطأ. + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass: هو مجرد أمر ﻻ تفعل شيء. عادة تقوم بتصحيح الخطأ هنا. +except (TypeError, NameError): + pass # يمكنك التحكم في أكثر من خطأ في نفس الوقت، إذا أقتضت الضرورة +else: # فقرة اختيارية في مجموعة try/except. يجب أن يتبع جميع مجموعات معارضة الأخطاء + print("All good!") # تُنفذ في حالة أن السطور البرمجية داخل ال try لم ترفع أي خطأ +finally: # تُنفذ في كل الحالات + print("We can clean up resources here") + +# بدلا من مجموعة try/finally لتنظيف الموارد يمكنك استخدام سطر with +with open("myfile.txt") as f: + for line in f: + print(line) + +# يتيح البايثون تجريد أساسي يسمى المُكرَر. +# المُكرٍَر عبارة عن متغير يمكن التعامل معه كسلسلة. +# الكائن الذي يعود من دالة نطاق، يسمى المُكرَر. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']) +# هذا عبارة عن متغير يعرض عناصر مفاتيح المُكرَر. + +# يمكننا الدوران حوله. +for i in our_iterable: + print(i) # Prints one, two, three + +# مع ذلك ﻻ يمكننا الوصول للعناصر بالمؤشر. +our_iterable[1] # يرفع خطأ TypeError + +# المُكرَر هو عبارة عن عنصر يعلم كيفية إنشاء مُكرِر +our_iterator = iter(our_iterable) + +# المُكرِر هو عبارة عن عنصر يمكنه تذكر الحالة أثناء مرورنا بعناصره. +# يمكننا الحصول على العنصر التالي عن طريق "next()" +next(our_iterator) # => "one" + +# يحفظ الحالة أثناء الدوران. +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# بعد عرض المُكرِر كل عناصره، يرفع استثناء StopIteration +next(our_iterator) # يرفع StopIteration + +# يمكنك الحصول على كل عناصر المُكرر بمناداة دالة list() عليه. +list(filled_dict.keys()) # => Returns ["one", "two", "three"] + + +#################################################### +## 4. الدوال +#################################################### + +# إستخدم "def" لإنشاء دوال جديدة. +def add(x, y): + print("x is {} and y is {}".format(x, y)) + return x + y # يمكنك إرجاع قيمة من الدالة بسطر return + +# مناداة دوال بمعطيات +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 + +# طريقة أخرى لمناداة دوال باستخدام كلمات مفتاحية. +add(y=6, x=5) # الكلمة المفتاحية يمكن أن تُعطى بأي ترتيب. + +# يمكنك تعريف دوال تأخذ عدد متغير من المُعطيات + +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + +# يمكنك تعريف دوال تأخذ عدد متغير من الكلمات المفتاحية كمعطيات أيضا. +def keyword_args(**kwargs): + return kwargs + +# هيا ننادي على الدالة لنرى ماذا سيحدث +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# يمكنك فعل الأثنين معًا في نفس الوقت، إذا أردت +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# عندما تنادي على دوال، يمكنك عمل عكس المعطيات/المفاتيح! +# استخدم * لتوسعة الصفوف، واستخدم ** لتوسعة المفاتيح. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # مساوٍ ل all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # مساوٍ ل to all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # مساوٍ ل to all_the_args(1, 2, 3, 4, a=3, b=4) + +# يقوم بإعادة مجموعة من القيم (بتعيين الصفوف) +def swap(x, y): + return y, x # يقوم بإعادة مجموعة من القيم على شكل صفوف بدون الأقواس + # (لاحظ: الأقواس حُذفت لكن يمكن إضافتها) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # مرة أخرى الأقواس حُذفت لكن يمكن إضافتها. + +# مجال الدالة +x = 5 + +def set_x(num): + # المتغير المحلي x ليس هو المتغير العام x + x = num # => 43 + print(x) # => 43 + +def set_global_x(num): + global x + print(x) # => 5 + x = num #المتغير العام x الأن مساوٍ ل 6 + print(x) # => 6 + +set_x(43) +set_global_x(6) + + +# بايثون تدعم دوال الفئة أولية [first class functions] (أي أنه يمكن إرسال الدوال كمعطيات لدوال أخرى) +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# يوجد أيضا دوال مجهولة +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# يوجد دوال مدمجة من درجة أعلى +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# يمكن إشتمال القوائم على خرائط وفلاتر حسنة الشكل +# هذه القوائم تحفظ المُخرج كقائمة والتي بدورها يمكن أن تكون قائمة مداخلة +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# يمكنك بناء مجموعات وقواميس على هذا المنوال أيضا +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +## 5. الوحدات البرمجية (الموديولات) +#################################################### + +# يمكنك استدعاء موديولات +import math +print(math.sqrt(16)) # => 4.0 + +# يمكنك استدعاء دالة معينة من موديول +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# يمكنك استدعاء كل الدوال من مديول. +# تحذير: هذا الفعل غير موصى به +from math import * + +# يمكنك تصغير اسم موديول +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# موديولات البايثون عبارة عن ملفات بايثون عادية. +# يمكنك كتابة الموديولات الخاصة بك, واستدعاها. +# اسم الموديول يكون نفس اسم الملف. + +# يمكنك معرفة أي الدوال والصفات مُعرفة في الموديول. +import math +dir(math) + +# إذا كان لديك سكربت بايثون يسمى math.py +# في نفس المجلد الموجود به السكربت الخاص بك، الملف الخاص بك math.py +# سَيُستدعى بدلا من موديول البايثون بنفس الاسم +# هذا يحدث لأن المجلدات المحلية لديها أولوية عن مكتبات البايثون المُدمجة + + +#################################################### +## 6. الفئات/القوالب (الكلاسات) +#################################################### + +# نستخدم السطر البرمجي "class" لإنشاء قالب +class Human: + + # صفة القالب. مشتركة بين كل نسخ القالب + species = "H. sapiens" + + # مُهيئ إبتدائي، يُنادى عليه عندما يتم استدعاء القالب. + # لاحظ أن الشرطة السٌفلية المُكررة مرتين __ قبل وبعد الاسم تُعبر عن الكائنات + # أو الصفات المُستخدمة عن طريق بايثون لكنها تعيش في مساحة تحكم المُستخدم. + # العمليات -الدوال- (أو الكائنات أو الصفات) مثل: __init__, __str__,__repr__ ألخ. + # تُسمى عمليات خاصة (أو أحيانا تسمى عمليات سحرية أو dunder methods) + # يجب عليك ألا تُسمي مثل هذه الاسماء بنفسك. + def __init__(self, name): + # ساوِ المُعطى بالصفة name الخاصة بهذه النسخة من القالب. + self.name = name + + # هيئ الصفة + self._age = 0 + + # عملية/دالة خاصة بنسخة القالب. كل العمليات تأخذ "self" كأول مُعطى + # An instance method. All methods take "self" as the first argument + def say(self, msg): + print("{name}: {message}".format(name=self.name, message=msg)) + + # عملية أخرى خاصة بنسخة القالب. + def sing(self): + return 'yo... yo... microphone check... one two... one two...' + + # عمليات القالب مشتركة بين كل أجزاء القالب + # يتم مناداتهم عن طريق جعل القالب المُنادي أول معطى + # They are called with the calling class as the first argument + @classmethod + def get_species(cls): + return cls.species + + # تُنادى العملية الثابتة بدون قالب أو نسخة قالب + @staticmethod + def grunt(): + return "*grunt*" + + # الخاصية تشبه تماما إمر الطلب + # تُحَوِل العملية age() إلي صفة مقروءة فقط بنفس الاسم. + # ﻻ حاجة لكتابة أوامر طلب أو تهيئة + @property + def age(self): + return self._age + + # هذا يتيح تهيئة الخاصية + @age.setter + def age(self, age): + self._age = age + + # هذا يتيح حذف الخاصية + @age.deleter + def age(self): + del self._age + + +# عندما يقرأ مُترجم البايثون ملف مصدري يقوم بتنفيذ كل الكود. +# فحص ال __name__ يجعل هذا الجزء من الكود يُنَفَذ فقط +# في حالة أن هذا الموديول هو البرنامج الرئيسي +if __name__ == '__main__': + # Instantiate a class + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i و j نُسخ من النوع Human, أول بكلمات أخرى: هما كائنات للقالب Human + + # نادي على عملية القالب + i.say(i.get_species()) # "Ian: H. sapiens" + # عدل الخاصية المُشتركة + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # نادي على العملية الثابتة + print(Human.grunt()) # => "*grunt*" + + # لا يمكن مناداة العملية الثابتة من نسخة الكائن + # لأن i.grunt() سيقوم تلقائيا بوضع "self" (الكائن i) كمُعطى للعملية + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # حدًث الخاصية لهذه النسخة + i.age = 42 + # أحصل على الخاصية + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # إحذف الخاصية + del i.age + # i.age # => سوف يرفع استثناء AttributeError + + +#################################################### +## 6.1 الإرث +#################################################### + +# الإرث يتيح لقالب ابن أن يُعَرف ويرث بعض عمليات/دوال ومتغيرات القالب الأب. + +# باستخدام القالب Human المُعَرف بالأعلى كأساس أو كقالب أب، +# يمكننا تعريف قالب ابن،Superhero ، يرث متغيرات القالب مثل "species", "name", و "age"، +# وأيضا العمليات، مثل "sing", "grunt" +# من القالب Human، لكنه أيضا لديه خواصه الفريدة + +# للاستفادة من التقطيع بالملف يمكنك وضع القوالب بالأعلى في ملفاتهم الخاصة، +# مثلا، human.py + +# لاستيراد دالة من ملف أخر استخدم الطريقة التالية +# from "اسم الملف بدون مُلحق" import "اسم الدالة أو القالب" + +from human import Human + +# حدد القالب/ات الأب كمُعطى أثناء تعريف القالب. +class Superhero(Human): + + # إذا أردت أن يرث القالب الابن كل تعريفات القالب الأب بدون تعديل + # يمكنك استخدام الكلمة المفتاحية "pass" (بدون شيء أخر) + # لكن في هذه الحالة تم أهمالها لإنشاء قالب ابن فريد: + # pass + + # القوالب الابن يمكنها تعديل صفات القوالب الأب + species = 'Superhuman' + + # القوالب الابن ترث تلقائيا عمليات الإنشاء الخاصة بالقالب الأب بالإضافة إلي مُعطياتهم + # لكن يمكن أيضا تعريف مُعطيات إضافية أو تعريفات + # وتعديل العمليات مثل منشيء القالب. + # هذا المُنشيء يرث المُعطى "name" من القالب "Human" + # ويضيف المعطيات"superpower" و "movies": + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # إضافة صفة جديدة للقالب + self.fictional = True + self.movie = movie + # كن على علم بالقيم الافتراضية المتغيرة، حيث أن القيم الافتراضية تُشارك + self.superpowers = superpowers + + # الدالة "super" تتيح لك الوصول لعمليات القالب الأب + # التي تم تغييرها عن طريق الابن، في هذه الحالة، العملية __init__< + # هذا السطر يُنادي على منشيء القالب الأب. + super().__init__(name) + + # تعديل العملية sing + def sing(self): + return 'Dun, dun, DUN!' + + # إضافة عملية جديدة للنسخة + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # فحص نوع النسخة + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # إحصل على ترتيب قرار البحث للعملية (Method Resolution search Order) المُستخدمة بواسطة العمليات getattr() و super() + # هذه الصفة ديناميكية ويمكن أن تُحَدًث. + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # نادي العملية الأب لكن استخدم صفات القالب الخاص بها. + print(sup.get_species()) # => Superhuman + + # نادي العملية المُعدلة. + print(sup.sing()) # => Dun, dun, DUN! + + # نادي العملية من القالب Human + sup.say('Spoon') # => Tick: Spoon + + # نادي عملية موجودة فقط في Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # وَرَثَ صفات القالب + sup.age = 31 + print(sup.age) # => 31 + + # صفة موجودة فقط في القالب Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) + +#################################################### +## 6.2 الإرث المُتعدد +#################################################### + +# تعريف قالب أخرA +# bat.py +class Bat: + + species = 'Baty' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # هذا القالب لديه عملية تسمى say + def say(self, msg): + msg = '... ... ...' + return msg + + # ولديه عمليته الخاصة به أيضا + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + +# تعريف قالب أخر يرث من Superhero و Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# عَرٍف Batman كقالب ابن يرث من كلا من Superhero و Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # عادة لكي ترث صفة يجد أن تنادي على super: + # super(Batman, self).__init__(*args, **kwargs) + # لكننا في هذه الحالة نتعامل مع إرث متعدد هنا، و super() + # تعمل فقط مع القالب التالي في قائمة ال MRO. + # لذا بدلا من ذلك ننادي على __init__ صراحة لكل الأباء. + # استخدام *args و **kwargs يتيح طريقة نظيفة لتمرير المعطيات. + # لكل أب "تقشير طبقة من البصل". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # تعديل قيمة الصفة name + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # إحصل على ترتيب قرار البحث للعملية (Method Resolution search Order) المُستخدمة بواسطة العمليات getattr() و super() + # هذه الصفة ديناميكية ويمكن أن تُحَدًث. + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # نادي على العملية الخاصة بالأب لكن استخدم الصفات الخاصة بالقالب الابن + print(sup.get_species()) # => Superhuman + + # نادي على العملية المُعدلة + print(sup.sing()) # => nan nan nan nan nan batman! + + # نادي على العملية من القالب Human, لأن الترتيب في الأرث مهم. + sup.say('I agree') # => Sad Affleck: I agree + + # نادي على العملية الموجودة فقط في القالب الأب الثاني + print(sup.sonar()) # => ))) ... ((( + + # الصفة الموروثة من القالب الأب + sup.age = 100 + print(sup.age) # => 100 + + # الصفة الموروثة من القالب الأب الثاني، الذي تم تعديل قيمته الافتراضية + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + + +#################################################### +## 7. مُتَقدم +#################################################### + +# المولدات تُساعدك على كتابة كود كسول. +def double_numbers(iterable): + for i in iterable: + yield i + i + +# المولدات فعالة من حيث الذاكرة، لأنها تُحمٍل الذاكرة بالبيانات التي تحتاج +# لإجراء العملية عليها في الخطوة التالية في المُكَرِر. +# هذا يتيح إجراء عمليات على قيم كبيرة ممنوعة في حالات أخرى. +# ﻻحظ: `range` بديل ل `xrange` في بايثون 3. +for i in double_numbers(range(1, 900000000)): # `range` is a generator. + print(i) + if i >= 30: + break + +# كما يمكنك إنشاء قوائم اشتمال، يمكنك إنشاء مولدات اشتمال أيضا +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # prints -1 -2 -3 -4 -5 to console/terminal + +# يمكنك أيضا تغيير نوع مولد الاشتمال مباشرة إلي قائمة +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# المُحسنات +# في هذا المثال الدالة`beg` تُغلف الدالة `say`. +# إذا كانت say_please تساوي True +# إذا ستُغير الرسالة الراجعة من الدالة +from functools import wraps + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( +``` + +## جاهز للمزيد? + +### مجانا عبر الانترنت + +* [أتمتتة المهمات المُملة عبر بايثون](https://automatetheboringstuff.com) +* [أفكار لمشروعات بلغة البايثون](http://pythonpracticeprojects.com) +* [التوثيقات الرسمية](http://docs.python.org/3/) +* [دليل المُسافر لبايثون](http://docs.python-guide.org/en/latest/) +* [دورة بايثون](http://www.python-course.eu/index.php) +* [أولى الخطوات مع بايثون](https://realpython.com/learn/python-first-steps/) +* [قائمة مُختارة من إطارات عمل بايثون الرائعة, المكتبات والبرمجيات](https://github.com/vinta/awesome-python) +* [ثلاثون خاصية وخدعة للغة البايثون ربما لم تعرف بها](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [الدليل الرسمي لنمط البايثون](https://www.python.org/dev/peps/pep-0008/) +* [بايثون 3 دوائر علوم الحاسب](http://cscircles.cemc.uwaterloo.ca/) +* [غُص في بايثون 3](http://www.diveintopython3.net/index.html) +* [دورة سريعة في البايثون للعلماء](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/awk.html.markdown b/awk.html.markdown index 3d2c4ccb..3b6e34b4 100644 --- a/awk.html.markdown +++ b/awk.html.markdown @@ -10,7 +10,7 @@ AWK is a standard tool on every POSIX-compliant UNIX system. It's like flex/lex, from the command-line, perfect for text-processing tasks and other scripting needs. It has a C-like syntax, but without mandatory semicolons (although, you should use them anyway, because they are required -when you're writing one-liners, something AWK excells at), manual memory +when you're writing one-liners, something AWK excels at), manual memory management, or static typing. It excels at text processing. You can call to it from a shell script, or you can use it as a stand-alone scripting language. @@ -32,7 +32,7 @@ pattern2 { action; } # There is an implied loop and AWK automatically reads and parses each # record of each file supplied. Each record is split by the FS delimiter, # which defaults to white-space (multiple spaces,tabs count as one) -# You cann assign FS either on the command line (-F C) or in your BEGIN +# You can assign FS either on the command line (-F C) or in your BEGIN # pattern # One of the special patterns is BEGIN. The BEGIN pattern is true @@ -238,7 +238,7 @@ function io_functions( localvar) { # handle for you when you use something that needs one. The string you used # for this can be treated as a file handle, for purposes of I/O. This makes # it feel sort of like shell scripting, but to get the same output, the string - # must match exactly, so use a vaiable: + # must match exactly, so use a variable: outfile = "/tmp/foobar.txt"; diff --git a/bash.html.markdown b/bash.html.markdown index 8c40931e..0385c46d 100644 --- a/bash.html.markdown +++ b/bash.html.markdown @@ -20,21 +20,23 @@ contributors: filename: LearnBash.sh --- -Bash is a name of the unix shell, which was also distributed as the shell for the GNU operating system and as default shell on Linux and Mac OS X. -Nearly all examples below can be a part of a shell script or executed directly in the shell. +Bash is a name of the unix shell, which was also distributed as the shell +for the GNU operating system and as default shell on Linux and Mac OS X. +Nearly all examples below can be a part of a shell script +or executed directly in the shell. [Read more here.](http://www.gnu.org/software/bash/manual/bashref.html) ```bash #!/usr/bin/env bash -# First line of the script is shebang which tells the system how to execute +# First line of the script is the shebang which tells the system how to execute # the script: http://en.wikipedia.org/wiki/Shebang_(Unix) # As you already figured, comments start with #. Shebang is also a comment. # Simple hello world example: echo Hello world! # => Hello world! -# Each command starts on a new line, or after semicolon: +# Each command starts on a new line, or after a semicolon: echo 'This is the first line'; echo 'This is the second line' # => This is the first line # => This is the second line @@ -47,7 +49,7 @@ Variable = "Some string" # => returns error "Variable: command not found" # Bash will decide that Variable is a command it must execute and give an error # because it can't be found. -# Or like this: +# Nor like this: Variable= 'Some string' # => returns error: "Some string: command not found" # Bash will decide that 'Some string' is a command it must execute and give an # error because it can't be found. (In this case the 'Variable=' part is seen @@ -65,8 +67,9 @@ echo '$Variable' # => $Variable # Parameter expansion ${ }: echo ${Variable} # => Some string # This is a simple usage of parameter expansion -# Parameter Expansion gets a value from a variable. It "expands" or prints the value -# During the expansion time the value or parameter are able to be modified +# Parameter Expansion gets a value from a variable. +# It "expands" or prints the value +# During the expansion time the value or parameter can be modified # Below are other modifications that add onto this expansion # String substitution in variables @@ -114,8 +117,8 @@ echo {1..10} # => 1 2 3 4 5 6 7 8 9 10 echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z # This will output the range from the start value to the end value -# Builtin variables: -# There are some useful builtin variables, like +# Built-in variables: +# There are some useful built-in variables, like echo "Last program's return value: $?" echo "Script's PID: $$" echo "Number of arguments passed to script: $#" @@ -127,7 +130,7 @@ echo "Script's arguments separated into different variables: $1 $2..." # Our current directory is available through the command `pwd`. # `pwd` stands for "print working directory". -# We can also use the builtin variable `$PWD`. +# We can also use the built-in variable `$PWD`. # Observe that the following are equivalent: echo "I'm in $(pwd)" # execs `pwd` and interpolates output echo "I'm in $PWD" # interpolates the variable @@ -143,7 +146,7 @@ read Name # Note that we didn't need to declare a new variable echo Hello, $Name! # We have the usual if structure: -# use 'man test' for more info about conditionals +# use `man test` for more info about conditionals if [ $Name != $USER ] then echo "Your name isn't your username" @@ -180,7 +183,7 @@ then echo "This will run if $Name is Daniya OR Zach." fi -# There is also the =~ operator, which tests a string against a Regex pattern: +# There is also the `=~` operator, which tests a string against a Regex pattern: Email=me@example.com if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]] then @@ -190,9 +193,9 @@ fi # which are subtly different from single [ ]. # See http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs for more on this. -# Redefine command 'ping' as alias to send only 5 packets +# Redefine command `ping` as alias to send only 5 packets alias ping='ping -c 5' -# Escape alias and use command with this name instead +# Escape the alias and use command with this name instead \ping 192.168.1.1 # Print all aliases alias -p @@ -205,14 +208,14 @@ echo $(( 10 + 5 )) # => 15 # directory with the ls command: ls # Lists the files and subdirectories contained in the current directory -# These commands have options that control their execution: +# This command has options that control its execution: ls -l # Lists every file and directory on a separate line ls -t # Sorts the directory contents by last-modified date (descending) ls -R # Recursively `ls` this directory and all of its subdirectories # Results of the previous command can be passed to the next command as input. -# grep command filters the input with provided patterns. That's how we can list -# .txt files in the current directory: +# The `grep` command filters the input with provided patterns. +# That's how we can list .txt files in the current directory: ls -l | grep "\.txt" # Use `cat` to print files to stdout: @@ -280,10 +283,17 @@ EOF # Run the hello.py Python script with various stdin, stdout, and # stderr redirections: python hello.py < "input.in" # pass input.in as input to the script + python hello.py > "output.out" # redirect output from the script to output.out + python hello.py 2> "error.err" # redirect error output to error.err -python hello.py > "output-and-error.log" 2>&1 # redirect both output and errors to output-and-error.log -python hello.py > /dev/null 2>&1 # redirect all output and errors to the black hole, /dev/null, i.e., no output + +python hello.py > "output-and-error.log" 2>&1 +# redirect both output and errors to output-and-error.log + +python hello.py > /dev/null 2>&1 +# redirect all output and errors to the black hole, /dev/null, i.e., no output + # The output error will overwrite the file if it exists, # if you want to append instead, use ">>": python hello.py >> "output.out" 2>> "error.err" @@ -312,11 +322,11 @@ rm -r tempDir/ # recursively delete # current directory. echo "There are $(ls | wc -l) items here." -# The same can be done using backticks `` but they can't be nested - the preferred way -# is to use $( ). +# The same can be done using backticks `` but they can't be nested - +#the preferred way is to use $( ). echo "There are `ls | wc -l` items here." -# Bash uses a case statement that works similarly to switch in Java and C++: +# Bash uses a `case` statement that works similarly to switch in Java and C++: case "$Variable" in #List patterns for the conditions you want to meet 0) echo "There is a zero.";; @@ -324,7 +334,7 @@ case "$Variable" in *) echo "It is not null.";; esac -# for loops iterate for as many arguments given: +# `for` loops iterate for as many arguments given: # The contents of $Variable is printed three times. for Variable in {1..3} do @@ -345,14 +355,14 @@ done # => 3 # They can also be used to act on files.. -# This will run the command 'cat' on file1 and file2 +# This will run the command `cat` on file1 and file2 for Variable in file1 file2 do cat "$Variable" done # ..or the output from a command -# This will cat the output from ls. +# This will `cat` the output from `ls`. for Output in $(ls) do cat "$Output" @@ -432,8 +442,8 @@ grep "^foo.*bar$" file.txt | grep -v "baz" # and not the regex, use fgrep (or grep -F) fgrep "foobar" file.txt -# The trap command allows you to execute a command whenever your script -# receives a signal. Here, trap will execute `rm` if it receives any of the +# The `trap` command allows you to execute a command whenever your script +# receives a signal. Here, `trap` will execute `rm` if it receives any of the # three listed signals. trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM @@ -442,7 +452,7 @@ NAME1=$(whoami) NAME2=$(sudo whoami) echo "Was $NAME1, then became more powerful $NAME2" -# Read Bash shell builtins documentation with the bash 'help' builtin: +# Read Bash shell built-ins documentation with the bash `help` built-in: help help help help for @@ -450,12 +460,12 @@ help return help source help . -# Read Bash manpage documentation with man +# Read Bash manpage documentation with `man` apropos bash man 1 bash man bash -# Read info documentation with info (? for help) +# Read info documentation with `info` (`?` for help) apropos info | grep '^info.*(' man info info info diff --git a/c++.html.markdown b/c++.html.markdown index 4113d5f4..3f5a2f4e 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -78,7 +78,7 @@ int* ip = nullptr; // The C++ standard version: #include <cstdio> -//The C standard version: +// The C standard version: #include <stdio.h> int main() @@ -257,7 +257,7 @@ fooRef = bar; cout << &fooRef << endl; //Still prints the address of foo cout << fooRef; // Prints "I am bar" -//The address of fooRef remains the same, i.e. it is still referring to foo. +// The address of fooRef remains the same, i.e. it is still referring to foo. const string& barRef = bar; // Create a const reference to bar. @@ -809,7 +809,103 @@ void doSomethingWithAFile(const std::string& filename) // all automatically destroy their contents when they fall out of scope. // - Mutexes using lock_guard and unique_lock -// containers with object keys of non-primitive values (custom classes) require + +///////////////////// +// Containers +///////////////////// + +// Containers or the Standard Template Library are some predefined templates. +// They manage the storage space for its elements and provide +// member functions to access and manipulate them. + +// Few containers are as follows: + +// Vector (Dynamic array) +// Allow us to Define the Array or list of objects at run time +#include <vector> +string val; +vector<string> my_vector; // initialize the vector +cin >> val; +my_vector.push_back(val); // will push the value of 'val' into vector ("array") my_vector +my_vector.push_back(val); // will push the value into the vector again (now having two elements) + +// To iterate through a vector we have 2 choices: +// Either classic looping (iterating through the vector from index 0 to its last index): +for (int i = 0; i < my_vector.size(); i++) { + cout << my_vector[i] << endl; // for accessing a vector's element we can use the operator [] +} + +// or using an iterator: +vector<string>::iterator it; // initialize the iterator for vector +for (it = my_vector.begin(); it != my_vector.end(); ++it) { + cout << *it << endl; +} + +// Set +// Sets are containers that store unique elements following a specific order. +// Set is a very useful container to store unique values in sorted order +// without any other functions or code. + +#include<set> +set<int> ST; // Will initialize the set of int data type +ST.insert(30); // Will insert the value 30 in set ST +ST.insert(10); // Will insert the value 10 in set ST +ST.insert(20); // Will insert the value 20 in set ST +ST.insert(30); // Will insert the value 30 in set ST +// Now elements of sets are as follows +// 10 20 30 + +// To erase an element +ST.erase(20); // Will erase element with value 20 +// Set ST: 10 30 +// To iterate through Set we use iterators +set<int>::iterator it; +for(it=ST.begin();it<ST.end();it++) { + cout << *it << endl; +} +// Output: +// 10 +// 30 + +// To clear the complete container we use Container_name.clear() +ST.clear(); +cout << ST.size(); // will print the size of set ST +// Output: 0 + +// NOTE: for duplicate elements we can use multiset +// NOTE: For hash sets, use unordered_set. They are more efficient but +// do not preserve order. unordered_set is available since C++11 + +// Map +// Maps store elements formed by a combination of a key value +// and a mapped value, following a specific order. + +#include<map> +map<char, int> mymap; // Will initialize the map with key as char and value as int + +mymap.insert(pair<char,int>('A',1)); +// Will insert value 1 for key A +mymap.insert(pair<char,int>('Z',26)); +// Will insert value 26 for key Z + +// To iterate +map<char,int>::iterator it; +for (it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << "->" << it->second << '\n'; +// Output: +// A->1 +// Z->26 + +// To find the value corresponding to a key +it = mymap.find('Z'); +cout << it->second; + +// Output: 26 + +// NOTE: For hash maps, use unordered_map. They are more efficient but do +// not preserve order. unordered_map is available since C++11. + +// Containers with object keys of non-primitive values (custom classes) require // compare function in the object itself or as a function pointer. Primitives // have default comparators, but you can override it. class Foo { @@ -822,12 +918,13 @@ struct compareFunction { return a.j < b.j; } }; -//this isn't allowed (although it can vary depending on compiler) -//std::map<Foo, int> fooMap; +// this isn't allowed (although it can vary depending on compiler) +// std::map<Foo, int> fooMap; std::map<Foo, int, compareFunction> fooMap; fooMap[Foo(1)] = 1; fooMap.find(Foo(1)); //true + /////////////////////////////////////// // Lambda Expressions (C++11 and above) /////////////////////////////////////// @@ -994,101 +1091,6 @@ cout << get<3>(concatenated_tuple) << "\n"; // prints: 15 cout << get<5>(concatenated_tuple) << "\n"; // prints: 'A' -///////////////////// -// Containers -///////////////////// - -// Containers or the Standard Template Library are some predefined templates. -// They manage the storage space for its elements and provide -// member functions to access and manipulate them. - -// Few containers are as follows: - -// Vector (Dynamic array) -// Allow us to Define the Array or list of objects at run time -#include <vector> -string val; -vector<string> my_vector; // initialize the vector -cin >> val; -my_vector.push_back(val); // will push the value of 'val' into vector ("array") my_vector -my_vector.push_back(val); // will push the value into the vector again (now having two elements) - -// To iterate through a vector we have 2 choices: -// Either classic looping (iterating through the vector from index 0 to its last index): -for (int i = 0; i < my_vector.size(); i++) { - cout << my_vector[i] << endl; // for accessing a vector's element we can use the operator [] -} - -// or using an iterator: -vector<string>::iterator it; // initialize the iterator for vector -for (it = my_vector.begin(); it != my_vector.end(); ++it) { - cout << *it << endl; -} - -// Set -// Sets are containers that store unique elements following a specific order. -// Set is a very useful container to store unique values in sorted order -// without any other functions or code. - -#include<set> -set<int> ST; // Will initialize the set of int data type -ST.insert(30); // Will insert the value 30 in set ST -ST.insert(10); // Will insert the value 10 in set ST -ST.insert(20); // Will insert the value 20 in set ST -ST.insert(30); // Will insert the value 30 in set ST -// Now elements of sets are as follows -// 10 20 30 - -// To erase an element -ST.erase(20); // Will erase element with value 20 -// Set ST: 10 30 -// To iterate through Set we use iterators -set<int>::iterator it; -for(it=ST.begin();it<ST.end();it++) { - cout << *it << endl; -} -// Output: -// 10 -// 30 - -// To clear the complete container we use Container_name.clear() -ST.clear(); -cout << ST.size(); // will print the size of set ST -// Output: 0 - -// NOTE: for duplicate elements we can use multiset -// NOTE: For hash sets, use unordered_set. They are more efficient but -// do not preserve order. unordered_set is available since C++11 - -// Map -// Maps store elements formed by a combination of a key value -// and a mapped value, following a specific order. - -#include<map> -map<char, int> mymap; // Will initialize the map with key as char and value as int - -mymap.insert(pair<char,int>('A',1)); -// Will insert value 1 for key A -mymap.insert(pair<char,int>('Z',26)); -// Will insert value 26 for key Z - -// To iterate -map<char,int>::iterator it; -for (it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << "->" << it->second << '\n'; -// Output: -// A->1 -// Z->26 - -// To find the value corresponding to a key -it = mymap.find('Z'); -cout << it->second; - -// Output: 26 - -// NOTE: For hash maps, use unordered_map. They are more efficient but do -// not preserve order. unordered_map is available since C++11. - /////////////////////////////////// // Logical and Bitwise operators ////////////////////////////////// diff --git a/crystal.html.markdown b/crystal.html.markdown index 8210b443..9fae9da3 100644 --- a/crystal.html.markdown +++ b/crystal.html.markdown @@ -25,17 +25,19 @@ true.class #=> Bool 1.class #=> Int32 -# Four signed integer types -1_i8.class #=> Int8 -1_i16.class #=> Int16 -1_i32.class #=> Int32 -1_i64.class #=> Int64 - -# Four unsigned integer types -1_u8.class #=> UInt8 -1_u16.class #=> UInt16 -1_u32.class #=> UInt32 -1_u64.class #=> UInt64 +# Five signed integer types +1_i8.class #=> Int8 +1_i16.class #=> Int16 +1_i32.class #=> Int32 +1_i64.class #=> Int64 +1_i128.class #=> Int128 + +# Five unsigned integer types +1_u8.class #=> UInt8 +1_u16.class #=> UInt16 +1_u32.class #=> UInt32 +1_u64.class #=> UInt64 +1_u128.class #=> UInt128 2147483648.class #=> Int64 9223372036854775808.class #=> UInt64 diff --git a/cs-cz/python3.html.markdown b/cs-cz/python3.html.markdown index dbaae88b..2cbf52e6 100644 --- a/cs-cz/python3.html.markdown +++ b/cs-cz/python3.html.markdown @@ -572,7 +572,7 @@ Clovek.odkaslej_si() # => "*ehm*" # Lze importovat moduly import math -print(math.sqrt(16.0)) # => 4 +print(math.sqrt(16.0)) # => 4.0 # Lze také importovat pouze vybrané funkce z modulu from math import ceil, floor diff --git a/dart.html.markdown b/dart.html.markdown index e12a4ed5..07f755f7 100644 --- a/dart.html.markdown +++ b/dart.html.markdown @@ -25,42 +25,42 @@ import "dart:math" as DM; // The fat arrow function declaration has an implicit return for the result of // the expression. example1() { - example1nested1() { - example1nested2() => print("Example1 nested 1 nested 2"); - example1nested2(); + nested1() { + nested2() => print("Example1 nested 1 nested 2"); + nested2(); } - example1nested1(); + nested1(); } // Anonymous functions don't include a name. example2() { - example2nested1(fn) { + nested1(fn) { fn(); } - example2nested1(() => print("Example2 nested 1")); + nested1(() => print("Example2 nested 1")); } // When a function parameter is declared, the declaration can include the // number of parameters the function takes by specifying the names of the // parameters it takes. example3() { - example3nested1(fn(informSomething)) { - fn("Example3 nested 1"); + planA(fn(informSomething)) { + fn("Example3 plan A"); } - example3planB(fn) { // Or don't declare number of parameters. + planB(fn) { // Or don't declare number of parameters. fn("Example3 plan B"); } - example3nested1((s) => print(s)); - example3planB((s) => print(s)); + planA((s) => print(s)); + planB((s) => print(s)); } // Functions have closure access to outer variables. var example4Something = "Example4 nested 1"; example4() { - example4nested1(fn(informSomething)) { + nested1(fn(informSomething)) { fn(example4Something); } - example4nested1((s) => print(s)); + nested1((s) => print(s)); } // Class declaration with a sayIt method, which also has closure access @@ -81,9 +81,9 @@ example5() { // Where classBody can include instance methods and variables, but also // class methods and variables. class Example6Class { - var example6InstanceVariable = "Example6 instance variable"; + var instanceVariable = "Example6 instance variable"; sayIt() { - print(example6InstanceVariable); + print(instanceVariable); } } example6() { @@ -92,12 +92,12 @@ example6() { // Class methods and variables are declared with "static" terms. class Example7Class { - static var example7ClassVariable = "Example7 class variable"; + static var classVariable = "Example7 class variable"; static sayItFromClass() { - print(example7ClassVariable); + print(classVariable); } sayItFromInstance() { - print(example7ClassVariable); + print(classVariable); } } example7() { @@ -110,40 +110,40 @@ example7() { // or outside of class have to be constant. Strings and numbers are constant // by default. But arrays and maps are not. They can be made constant by // declaring them "const". -var example8A = const ["Example8 const array"], - example8M = const {"someKey": "Example8 const map"}; +var example8Array = const ["Example8 const array"], + example8Map = const {"someKey": "Example8 const map"}; example8() { - print(example8A[0]); - print(example8M["someKey"]); + print(example8Array[0]); + print(example8Map["someKey"]); } // Loops in Dart take the form of standard for () {} or while () {} loops, // slightly more modern for (.. in ..) {}, or functional callbacks with many // supported features, starting with forEach. -var example9A = const ["a", "b"]; +var example9Array = const ["a", "b"]; example9() { - for (var i = 0; i < example9A.length; i++) { - print("Example9 for loop '${example9A[i]}'"); + for (var i = 0; i < example9Array.length; i++) { + print("Example9 for loop '${example9Array[i]}'"); } var i = 0; - while (i < example9A.length) { - print("Example9 while loop '${example9A[i]}'"); + while (i < example9Array.length) { + print("Example9 while loop '${example9Array[i]}'"); i++; } - for (var e in example9A) { + for (var e in example9Array) { print("Example9 for-in loop '${e}'"); } - example9A.forEach((e) => print("Example9 forEach loop '${e}'")); + example9Array.forEach((e) => print("Example9 forEach loop '${e}'")); } // To loop over the characters of a string or to extract a substring. -var example10S = "ab"; +var example10String = "ab"; example10() { - for (var i = 0; i < example10S.length; i++) { - print("Example10 String character loop '${example10S[i]}'"); + for (var i = 0; i < example10String.length; i++) { + print("Example10 String character loop '${example10String[i]}'"); } - for (var i = 0; i < example10S.length; i++) { - print("Example10 substring loop '${example10S.substring(i, i + 1)}'"); + for (var i = 0; i < example10String.length; i++) { + print("Example10 substring loop '${example10String.substring(i, i + 1)}'"); } } diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown index ae29d6f9..d3e0fc26 100644 --- a/de-de/python-de.html.markdown +++ b/de-de/python-de.html.markdown @@ -442,7 +442,7 @@ Human.grunt() #=> "*grunt*" # Wir können Module importieren import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Wir können auch nur spezielle Funktionen eines Moduls importieren from math import ceil, floor diff --git a/de-de/python3-de.html.markdown b/de-de/python3-de.html.markdown index b313727c..c383d742 100644 --- a/de-de/python3-de.html.markdown +++ b/de-de/python3-de.html.markdown @@ -555,7 +555,7 @@ Human.grunt() #=> "*grunt*" # Wir können Module importieren import math -print(math.sqrt(16)) #=> 4 +print(math.sqrt(16)) #=> 4.0 # Wir können auch nur spezielle Funktionen eines Moduls importieren from math import ceil, floor diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown index 25f2edc4..d0e3471a 100644 --- a/de-de/yaml-de.html.markdown +++ b/de-de/yaml-de.html.markdown @@ -10,7 +10,7 @@ lang: de-de YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann. -YAML ist ein Erweiterung von von JSON mit der Erweiterung um syntaktisch wichtige Zeilenumbrüche und Einrückungen, ähnlich wie auch in Python. Anders als in Python allerdings erlaubt YAML keine Tabulator-Zeichen. +YAML ist ein Erweiterung von JSON mit der Erweiterung um syntaktisch wichtige Zeilenumbrüche und Einrückungen, ähnlich wie auch in Python geschrieben werden können. Anders als in Python allerdings erlaubt YAML keine Tabulator-Zeichen. ```yaml # Kommentare in YAML schauen so aus. diff --git a/elixir.html.markdown b/elixir.html.markdown index e82509e7..7af29202 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -452,7 +452,7 @@ Agent.update(my_agent, fn colors -> ["blue" | colors] end) ## References * [Getting started guide](http://elixir-lang.org/getting-started/introduction.html) from the [Elixir website](http://elixir-lang.org) -* [Elixir Documentation](http://elixir-lang.org/docs/master/) +* [Elixir Documentation](https://elixir-lang.org/docs.html) * ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) by Dave Thomas * [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf) * ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert diff --git a/es-es/common-lisp-es.html.markdown b/es-es/common-lisp-es.html.markdown new file mode 100644 index 00000000..526ea621 --- /dev/null +++ b/es-es/common-lisp-es.html.markdown @@ -0,0 +1,692 @@ +--- + +language: "Common Lisp" +filename: commonlisp-es.lisp +contributors: + - ["Paul Nathan", "https://github.com/pnathan"] + - ["Rommel Martinez", "https://ebzzry.io"] +translators: + - ["ivanchoff", "https://github.com/ivanchoff"] + - ["Andre Polykanine", "https://github.com/Menelion"] +lang: es-es +--- + +Common Lisp es un lenguaje de proposito general y multiparadigma adecuado para una amplia variedad +de aplicaciones en la industria. Es frecuentemente referenciado como un lenguaje de programación +programable. + +EL punto de inicio clásico es [Practical Common Lisp](http://www.gigamonkeys.com/book/). Otro libro +popular y reciente es [Land of Lisp](http://landoflisp.com/). Un nuevo libro acerca de las mejores +prácticas, [Common Lisp Recipes](http://weitz.de/cl-recipes/), fue publicado recientemente. + +```lisp + +;;;----------------------------------------------------------------------------- +;;; 0. Sintaxis +;;;----------------------------------------------------------------------------- + +;;; Forma general + +;;; CL tiene dos piezas fundamentales en su sintaxis: ATOM y S-EXPRESSION. +;;; Típicamente, S-expressions agrupadas son llamadas `forms`. + +10 ; un atom; se evalua a sí mismo +:thing ; otro atom; evaluando el símbolo :thing +t ; otro atom, denotando true +(+ 1 2 3 4) ; una s-expression +'(4 :foo t) ; otra s-expression + + +;;; Comentarios + +;;; comentarios de una sola línea empiezan con punto y coma; usa cuatro para +;;; comentarios a nivel de archivo, tres para descripciones de sesiones, dos +;;; adentro de definiciones, y una para líneas simples. Por ejemplo, + +;;;; life.lisp + +;;; Foo bar baz, porque quu quux. Optimizado para máximo krakaboom y umph. +;;; Requerido por la función LINULUKO. + +(defun sentido (vida) + "Retorna el sentido de la vida calculado" + (let ((meh "abc")) + ;; llama krakaboom + (loop :for x :across meh + :collect x))) ; guarda valores en x, luego lo retorna + +;;; Comentarios de bloques, por otro lado, permiten comentarios de forma libre. estos son +;;; delimitados con #| y |# + +#| Este es un comentario de bloque el cual + puede abarcar multiples líneas y + #| + estos pueden ser anidados + |# +|# + + +;;; Entorno + +;;; Existe una variedad de implementaciones; La mayoría son conformes a los estándares. SBCL +;;; es un buen punto de inicio. Bibliotecas de terceros pueden instalarse fácilmente con +;;; Quicklisp + +;;; CL es usualmente desarrollado y un bucle de Lectura-Evaluación-Impresión (REPL), corriendo +;;; al mismo tiempo. El REPL permite la exploración interactiva del programa mientras este esta +;;; corriendo + + +;;;----------------------------------------------------------------------------- +;;; 1. Operadores y tipos de datos primitivos +;;;----------------------------------------------------------------------------- + +;;; Símbolos + +'foo ; => FOO Note que el símbolo es pasado a mayúsculas automáticamente. + +;;; INTERN manualmente crea un símbolo a partir de una cadena. + +(intern "AAAA") ; => AAAA +(intern "aaa") ; => |aaa| + +;;; Números + +9999999999999999999999 ; enteros +#b111 ; binario=> 7 +#o111 ; octal => 73 +#x111 ; hexadecimal => 273 +3.14159s0 ; simple +3.14159d0 ; double +1/2 ; proporciones +#C(1 2) ; números complejos + +;;; las funciones son escritas como (f x y z ...) donde f es una función y +;;; x, y, z, ... son los argumentos. + +(+ 1 2) ; => 3 + +;;; Si deseas crear datos literales use QUOTE para prevenir que estos sean evaluados + +(quote (+ 1 2)) ; => (+ 1 2) +(quote a) ; => A + +;;; La notación abreviada para QUOTE es ' + +'(+ 1 2) ; => (+ 1 2) +'a ; => A + +;;; Operaciones aritméticas básicas + +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + +;;; Boleanos + +t ; true; cualquier valor non-NIL es true +nil ; false; también, la lista vacia: () +(not nil) ; => T +(and 0 t) ; => T +(or 0 nil) ; => 0 + +;;; Caracteres + +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA + +;;; Cadenas son arreglos de caracteres de longitud fija + +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ; la barra invertida es un carácter de escape + +;;; Las cadenas pueden ser concatenadas + +(concatenate 'string "Hello, " "world!") ; => "Hello, world!" + +;;; Una cadena puede ser tratada como una secuencia de caracteres + +(elt "Apple" 0) ; => #\A + +;;; FORMAT es usado para crear salidas formateadas, va desde simple interpolación de cadenas +;;; hasta bucles y condicionales. El primer argumento de FORMAT determina donde irá la cadena +;;; formateada. Si este es NIL, FORMAT simplemente retorna la cadena formateada como un valor; +;;; si es T, FORMAT imprime a la salida estándar, usualmente la pantalla, luego este retorna NIL. + +(format nil "~A, ~A!" "Hello" "world") ; => "Hello, world!" +(format t "~A, ~A!" "Hello" "world") ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 2. Variables +;;;----------------------------------------------------------------------------- + +;;; Puedes crear una variable global (ámbito dinámico) usando DEFVAR y DEFPARAMETER +;;; el nombre de la variable puede usar cualquier carácter excepto: ()",'`;#|\ + +;;; La diferencia entre DEFVAR y DEFPARAMETER es que reevaluando una expresión +;;; DEFVAR no cambia el valor de la variable. DEFPARAMETER, por otro lado sí lo hace. + +;;; Por convención, variables de ámbito dinámico tienen "orejeras" en sus nombres. + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;;; Puedes usar también caracteres unicode. +(defparameter *AΛB* nil) + +;;; Accediendo a una variable sin asignar tienen como resultado el error +;;; UNBOUND-VARIABLE, sin embargo este es el comportamiento definido. no lo hagas + +;;; puedes crear enlaces locales con LET. en el siguiente código, `me` es asignado +;;; con "dance with you" solo dentro de (let ...). LET siempre retorna el valor +;;; del último `form`. + +(let ((me "dance with you")) me) ; => "dance with you" + + +;;;-----------------------------------------------------------------------------; +;;; 3. Estructuras y colecciones +;;;-----------------------------------------------------------------------------; + + +;;; Estructuras + +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) +(dog-p *rover*) ; => T +(dog-name *rover*) ; => "rover" + +;;; DOG-P, MAKE-DOG, y DOG-NAME son creados automáticamente por DEFSTRUCT + + +;;; Pares + +;;; CONS crea pares. CAR y CDR retornan la cabeza y la cola de un CONS-pair + +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + + +;;; Listas + +;;; Listas son estructuras de datos de listas enlazadas, hechas de pares CONS y terminan con un +;;; NIL (o '()) para marcar el final de la lista + +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) + +;;; LIST es una forma conveniente de crear listas + +(list 1 2 3) ; => '(1 2 3) + +;;; Cuando el primer argumento de CONS es un atom y el segundo argumento es una lista, +;;; CONS retorna un nuevo par CONS con el primer argumento como el primer elemento y el +;;; segundo argumento como el resto del par CONS + +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;;; Use APPEND para unir listas + +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; o CONCATENATE + +(concatenate 'list '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; las listas son un tipo de datos centrales en CL, por lo tanto hay una gran variedad +;;; de funcionalidades para ellas, algunos ejemplos son: + +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => NIL +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; Vectores + +;;; Vectores literales son arreglos de longitud fija + +#(1 2 3) ; => #(1 2 3) + +;;; Use CONCATENATE para juntar vectores + +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + + +;;; Arreglos + +;;; Vectores y cadenas son casos especiales de arreglos. + +;;; Arreglos bidimensionales + +(make-array (list 2 2)) ; => #2A((0 0) (0 0)) +(make-array '(2 2)) ; => #2A((0 0) (0 0)) +(make-array (list 2 2 2)) ; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;;; Precaución: los valores iniciales por defecto de MAKE-ARRAY son implementaciones definidas +;;; para definirlos explícitamente: + +(make-array '(2) :initial-element 'unset) ; => #(UNSET UNSET) + +;;; Para acceder al elemento en 1, 1, 1: + +(aref (make-array (list 2 2 2)) 1 1 1) ; => 0 + +;;; Este valor es definido por implementación: +;;; NIL en ECL, 0 en SBCL and CCL. + +;;; vectores ajustables + +;;; los vectores ajustables tienen la misma representación en la impresión como los vectores literales +;;; de longitud fija. + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) +*adjvec* ; => #(1 2 3) + +;;; Agregando nuevos elementos + +(vector-push-extend 4 *adjvec*) ; => 3 +*adjvec* ; => #(1 2 3 4) + + +;;; Conjuntos, ingenuamente son listas: + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;;; Sin embargo, necesitarás una mejor estructura de datos que listas enlazadas +;;; cuando trabajes con conjuntos de datos grandes + +;;; Los Diccionarios son implementados como tablas hash. + +;;; Crear tablas hash + +(defparameter *m* (make-hash-table)) + +;;; definir valor + +(setf (gethash 'a *m*) 1) + +;;; obtener valor + +(gethash 'a *m*) ; => 1, T + +;;; las expresiones en CL tienen la facultad de retornar multiples valores. + +(values 1 2) ; => 1, 2 + +;;; los cuales pueden ser asignados con MULTIPLE-VALUE-BIND + +(multiple-value-bind (x y) + (values 1 2) + (list y x)) + +; => '(2 1) + +;;; GETHASH es un ejemplo de una función que retorna multiples valores. El primer +;;; valor es el valor de la llave en la tabla hash: si la llave no existe retorna NIL. + +;;; El segundo valor determina si la llave existe en la tabla hash. si la llave no existe +;;; en la tabla hash retorna NIL. Este comportamiento permite verificar si el valor de una +;;; llave es actualmente NIL. + +;;; Obteniendo un valor no existente retorna NIL + +(gethash 'd *m*) ;=> NIL, NIL + +;;; Puedes declarar un valor por defecto para las llaves inexistentes + +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;;; Vamos a manejar los multiples valores de retornno en el código. + +(multiple-value-bind (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + + +;;;----------------------------------------------------------------------------- +;;; 3. Funciones +;;;----------------------------------------------------------------------------- + +;;; Use LAMBDA para crear funciones anónimas. las funciones siempre retornan el valor +;;; de la última expresión. la representación imprimible de una función varia entre +;;; implementaciones. + +(lambda () "Hello World") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}> + +;;; Use FUNCALL para llamar funciones anónimas. + +(funcall (lambda () "Hello World")) ; => "Hello World" +(funcall #'+ 1 2 3) ; => 6 + +;;; Un llamado a FUNCALL es también realizado cuando la expresión lambda es el CAR de +;;; una lista. + +((lambda () "Hello World")) ; => "Hello World" +((lambda (val) val) "Hello World") ; => "Hello World" + +;;; FUNCALL es usado cuando los argumentos son conocidos de antemano. +;;; de lo contrario use APPLY + +(apply #'+ '(1 2 3)) ; => 6 +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;;; Para nombrar una funcion use DEFUN + +(defun hello-world () "Hello World") +(hello-world) ; => "Hello World" + +;;; Los () en la definición anterior son la lista de argumentos + +(defun hello (name) (format nil "Hello, ~A" name)) +(hello "Steve") ; => "Hello, Steve" + +;;; las functiones pueden tener argumentos opcionales; por defecto son NIL + +(defun hello (name &optional from) + (if from + (format t "Hello, ~A, from ~A" name from) + (format t "Hello, ~A" name))) + +(hello "Jim" "Alpacas") ; => Hello, Jim, from Alpacas + +;;; Los valores por defecto pueden ser especificados + + +(defun hello (name &optional (from "The world")) + (format nil "Hello, ~A, from ~A" name from)) + +(hello "Steve") ; => Hello, Steve, from The world +(hello "Steve" "the alpacas") ; => Hello, Steve, from the alpacas + +;;; Las funciones también tienen argumentos llaves para permitir argumentos no positionados + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) + (format t "Hello, ~A ~A, from ~A" honorific name from)) + +(generalized-greeter "Jim") +; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + + +;;;----------------------------------------------------------------------------- +;;; 4. Igualdad +;;;----------------------------------------------------------------------------- + +;;; CL tiene un sistema sofisticado de igualdad. Una parte es tratada aquí. + +;;; Para números use `=` +(= 3 3.0) ; => T +(= 2 1) ; => NIL + +;;; Para identidad de objetos (aproximadamente) use EQL +(eql 3 3) ; => T +(eql 3 3.0) ; => NIL +(eql (list 3) (list 3)) ; => NIL + +;;; para listas, cadenas y bit vectores use EQUAL +(equal (list 'a 'b) (list 'a 'b)) ; => T +(equal (list 'a 'b) (list 'b 'a)) ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 5. Control de flujo +;;;----------------------------------------------------------------------------- + +;;; Condicionales + +(if t ; testar expresión + "this is true" ; then expression + "this is false") ; else expression +; => "this is true" + +;;; En condicionales, todo valor non-NIL es tratado como true + +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;;; COND en cadena una serie de pruebas para seleccionar un resultado +(cond ((> 2 2) (error "wrong!")) + ((< 2 2) (error "wrong again!")) + (t 'ok)) ; => 'OK + +;;; TYPECASE evalua sobre el tipo del valor +(typecase 1 + (string :string) + (integer :int)) +; => :int + + +;;; Bucles + +;;; Recursión + +(defun fact (n) + (if (< n 2) + 1 + (* n (fact(- n 1))))) + +(fact 5) ; => 120 + +;;; Iteración + +(defun fact (n) + (loop :for result = 1 :then (* result i) + :for i :from 2 :to n + :finally (return result))) + +(fact 5) ; => 120 + +(loop :for x :across "abcd" :collect x) +; => (#\a #\b #\c #\d) + +(dolist (i '(1 2 3 4)) + (format t "~A" i)) +; => 1234 + + +;;;----------------------------------------------------------------------------- +;;; 6. Mutación +;;;----------------------------------------------------------------------------- + +;;; use SETF para asignar un valor nuevo a una variable existente. Esto fue demostrado +;;; previamente en el ejemplo de la tabla hash. + +(let ((variable 10)) + (setf variable 2)) +; => 2 + +;;; Un estilo bueno de lisp es minimizar el uso de funciones destructivas y prevenir +;;; la mutación cuando sea posible. + + +;;;----------------------------------------------------------------------------- +;;; 7. Clases y objetos +;;;----------------------------------------------------------------------------- + +;;; No más clases de animales, tengamos transportes mecánicos impulsados por el humano + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "A human powered conveyance")) + +;;; Los argumentos de DEFCLASS, en orden son: +;;; 1. nombre de la clase +;;; 2. lista de superclases +;;; 3. slot list +;;; 4. Especificadores opcionales + +;;; cuando no hay lista de superclase, la lista vacia indica clase de +;;; objeto estándar, esto puede ser cambiado, pero no mientras no sepas +;;; lo que estas haciendo. revisar el arte del protocolo de meta-objetos +;;; para más información. + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + +;;; Invocando DESCRIBE en la clase HUMAN-POWERED-CONVEYANCE en REPL obtenemos: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #<STANDARD-CLASS +; HUMAN-POWERED-CONVEYANCE>: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;;; Tenga en cuenta el comportamiento reflexivo disponible. CL fue diseñado +;;; para ser un systema interactivo + +;;; para definir un método, encontremos la circunferencia de la rueda usando +;;; la ecuación C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;;; PI es definido internamente en CL + +;;; Supongamos que descubrimos que el valor de eficiencia del número de remeros +;;; en una canoa es aproximadamente logarítmico. Esto probablemente debería +;;; establecerse en el constructor / inicializador. + +;;; Para inicializar su instancia después de que CL termine de construirla: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + +;;; luego para construir una instancia y revisar la eficiencia promedio + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;----------------------------------------------------------------------------- +;;; 8. Macros +;;;----------------------------------------------------------------------------- + +;;; las Macros le permiten extender la sintaxis del lenguaje, CL no viene con +;;; un bucle WHILE, por lo tanto es facil escribirlo, Si obedecemos nuestros +;;; instintos de ensamblador, terminamos con: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" + (let ((block-name (gensym)) (done (gensym))) + `(tagbody + ,block-name + (unless ,condition + (go ,done)) + (progn + ,@body) + (go ,block-name) + ,done))) + +;;; revisemos la versión de alto nivel para esto: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" + `(loop while ,condition + do + (progn + ,@body))) + +;;; Sin embargo, con un compilador moderno, esto no es necesario; El LOOP se +;;; compila igualmente bien y es más fácil de leer. + +;;; Tenga en cuenta que se utiliza ```, así como `,` y `@`. ``` es un operador +;;; de tipo de cita conocido como quasiquote; permite el uso de `,` . `,` permite +;;; variables "entre comillas". @ interpola las listas. + +;;; GENSYM crea un símbolo único que garantiza que no existe en ninguna otra parte +;;; del sistema. Esto se debe a que las macros se expanden en el momento de la compilación +;;; y las variables declaradas en la macro pueden colisionar con las variables utilizadas +;;; en un código regular. + +;;; Consulte Practical Common Lisp y On Lisp para obtener más información sobre macros. +``` + + +## Otras Lecturas + +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Common Lisp: A Gentle Introduction to Symbolic Computation](https://www.cs.cmu.edu/~dst/LispBook/book.pdf) + + +## Información extra + +- [CLiki](http://www.cliki.net/) +- [common-lisp.net](https://common-lisp.net/) +- [Awesome Common Lisp](https://github.com/CodyReichert/awesome-cl) +- [Lisp Lang](http://lisp-lang.org/) + + +## Creditos + +Muchas Gracias a la gente de Scheme por proveer un gran punto de inicio +el cual puede ser movido fácilmente a Common Lisp + +- [Paul Khuong](https://github.com/pkhuong) para un buen repaso. diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown index a27203d1..2b8f498a 100644 --- a/es-es/python-es.html.markdown +++ b/es-es/python-es.html.markdown @@ -467,7 +467,7 @@ Humano.roncar() #=> "*roncar*" # Puedes importar módulos import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Puedes obtener funciones específicas desde un módulo from math import ceil, floor diff --git a/fr-fr/markdown-fr.html.markdown b/fr-fr/markdown-fr.html.markdown index b3b7de85..26c2546a 100644 --- a/fr-fr/markdown-fr.html.markdown +++ b/fr-fr/markdown-fr.html.markdown @@ -350,7 +350,7 @@ ne sont pas tres agréable d'utilisation. Mais si vous en avez besoin : ```md | Col1 | Col2 | Col3 | | :----------- | :------: | ------------: | -| Alignement Gauche | Centé | Alignement Droite | +| Alignement Gauche | Centré | Alignement Droite | | bla | bla | bla | ``` diff --git a/fr-fr/python-fr.html.markdown b/fr-fr/python-fr.html.markdown index d78291be..0ae410de 100644 --- a/fr-fr/python-fr.html.markdown +++ b/fr-fr/python-fr.html.markdown @@ -444,7 +444,7 @@ Human.grunt() #=> "*grunt*" # On peut importer des modules import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Et récupérer des fonctions spécifiques d'un module from math import ceil, floor diff --git a/hu-hu/python-hu.html.markdown b/hu-hu/python-hu.html.markdown index 9b55f8e2..01f1c414 100644 --- a/hu-hu/python-hu.html.markdown +++ b/hu-hu/python-hu.html.markdown @@ -656,7 +656,7 @@ i.age # => AttributeError hibát dob # Modulokat így lehet importálni import math -print math.sqrt(16) # => 4 +print math.sqrt(16) # => 4.0 # Lehetséges csak bizonyos függvényeket importálni egy modulból from math import ceil, floor diff --git a/it-it/logtalk-it.html.markdown b/it-it/logtalk-it.html.markdown index 7f1e9eeb..5cc53e6f 100644 --- a/it-it/logtalk-it.html.markdown +++ b/it-it/logtalk-it.html.markdown @@ -43,7 +43,7 @@ Un oggetto incapsula le dichiarazioni e le definizioni dei predicati. Gli oggett :- end_object. ``` -# Compilazione dei file sorgenti +# Compilazione e il caricamento dei file sorgenti Supponendo che il codice di cui sopra per l'oggetto `list` venga salvato in un file` list.lgt`, esso può essere compilato e caricato utilizzando il predicato predefiniti `logtalk_load/1` o la sua abbreviazione `{}/1`, con il percorso del file come argomento (l'estensione può essere omessa): @@ -52,6 +52,9 @@ Supponendo che il codice di cui sopra per l'oggetto `list` venga salvato in un f yes ``` +In generale, le entità potrebbero avere dipendenze sulle entità definite in altri file di origine (ad esempio le entità di biblioteca). Per caricare un file e tutte le sue dipendenze, la soluzione consigliata consiste nel definire un file _loader_ che carica tutti i file necessari per un'applicazione. Un file loader è semplicemente un file di origine, in genere denominato `loader.lgt`, che effettua chiamate ai predicati built-in `logtalk_load/1-2`, di solito +da una direttiva `initialization/1` per la portabilità e conformità agli standard. Caricatore file vengono forniti per tutte le librerie, strumenti ed esempi. + # Inviare un messaggio ad un oggetto L'operatore infisso `::/2` è usato per inviare messaggi ad un oggetto. Analogamente al Prolog, è possibile fare backtracking per le soluzioni alternative: diff --git a/it-it/python-it.html.markdown b/it-it/python-it.html.markdown index e81d1676..794e7a70 100644 --- a/it-it/python-it.html.markdown +++ b/it-it/python-it.html.markdown @@ -640,7 +640,7 @@ i.age # => Emette un AttributeError # Puoi importare moduli import math -print math.sqrt(16) # => 4 +print math.sqrt(16) # => 4.0 # Puoi ottenere specifiche funzione da un modulo from math import ceil, floor diff --git a/javascript.html.markdown b/javascript.html.markdown index ecaf02c5..c466c09b 100644 --- a/javascript.html.markdown +++ b/javascript.html.markdown @@ -510,6 +510,7 @@ for (var x in myObj){ // Hello world! // 43 // [Function: myFunc] +// true // To only consider properties attached to the object itself // and not its prototypes, use the `hasOwnProperty()` check. diff --git a/julia.html.markdown b/julia.html.markdown index 69b6aa0c..eabb988e 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -93,21 +93,22 @@ ascii("This is a string")[1] # Julia indexes from 1 # Otherwise, iterating over strings is recommended (map, for loops, etc). +# String can be compared lexicographically +"good" > "bye" # => true +"good" == "good" # => true +"1 + 2 = 3" == "1 + 2 = $(1 + 2)" # => true + # $ can be used for string interpolation: "2 + 2 = $(2 + 2)" # => "2 + 2 = 4" # You can put any Julia expression inside the parentheses. +# Printing is easy +println("I'm Julia. Nice to meet you!") # => I'm Julia. Nice to meet you! + # Another way to format strings is the printf macro from the stdlib Printf. using Printf @printf "%d is less than %f\n" 4.5 5.3 # => 5 is less than 5.300000 -# Printing is easy -println("I'm Julia. Nice to meet you!") # => I'm Julia. Nice to meet you! - -# String can be compared lexicographically -"good" > "bye" # => true -"good" == "good" # => true -"1 + 2 = 3" == "1 + 2 = $(1 + 2)" # => true #################################################### ## 2. Variables and Collections diff --git a/ko-kr/python-kr.html.markdown b/ko-kr/python-kr.html.markdown index ed377a99..0145754d 100644 --- a/ko-kr/python-kr.html.markdown +++ b/ko-kr/python-kr.html.markdown @@ -441,7 +441,7 @@ Human.grunt() #=> "*grunt*" # 다음과 같이 모듈을 임포트할 수 있습니다. import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # 모듈의 특정 함수를 호출할 수 있습니다. from math import ceil, floor diff --git a/latex.html.markdown b/latex.html.markdown index 874efeeb..c980f5e5 100644 --- a/latex.html.markdown +++ b/latex.html.markdown @@ -95,7 +95,7 @@ to the source code. Separate paragraphs by empty lines. -You need to add a dot after abbreviations (if not followed by a comma), because otherwise the spacing after the dot is too large: +You need to add a backslash after abbreviations (if not followed by a comma), because otherwise the spacing after the dot is too large: E.g., i.e., etc.\ are are such abbreviations. \section{Lists} diff --git a/logtalk.html.markdown b/logtalk.html.markdown index 5a52bd3c..ce907ee3 100644 --- a/logtalk.html.markdown +++ b/logtalk.html.markdown @@ -40,7 +40,7 @@ An object encapsulates predicate declarations and definitions. Objects can be cr :- end_object. ``` -# Compiling source files +# Compiling and loading source files Assuming that the code above for the `list` object is saved in a `list.lgt` file, it can be compiled and loaded using the `logtalk_load/1` built-in predicate or its abbreviation, `{}/1`, with the file path as argument (the extension can be omitted): @@ -49,6 +49,11 @@ Assuming that the code above for the `list` object is saved in a `list.lgt` file yes ``` +In general, entities may have dependencies on entities defined in other source files (e.g. library entities). To load a file and all its dependencies, the advised solution is to define a +_loader_ file that loads all the necessary files for an application. A loader file is simply a source file, typically named `loader.lgt`, that makes calls to the `logtalk_load/1-2` +built-in predicates, usually from an `initialization/1` directive for portability and +standards compliance. Loader files are provided for all libraries, tools, and examples. + # Sending a message to an object The `::/2` infix operator is used to send a message to an object. As in Prolog, we can backtrack for alternative solutions: diff --git a/lua.html.markdown b/lua.html.markdown index 32174a81..0a7c4f00 100644 --- a/lua.html.markdown +++ b/lua.html.markdown @@ -12,13 +12,15 @@ filename: learnlua.lua Adding two ['s and ]'s makes it a multi-line comment. --]] --------------------------------------------------------------------------------- + +---------------------------------------------------- -- 1. Variables and flow control. --------------------------------------------------------------------------------- +---------------------------------------------------- num = 42 -- All numbers are doubles. --- Don't freak out, 64-bit doubles have 52 bits for storing exact int --- values; machine precision is not a problem for ints that need < 52 bits. +-- Don't freak out, 64-bit doubles have 52 bits for +-- storing exact int values; machine precision is +-- not a problem for ints that need < 52 bits. s = 'walternate' -- Immutable strings like Python. t = "double-quotes are also fine" @@ -58,15 +60,10 @@ aBoolValue = false -- Only nil and false are falsy; 0 and '' are true! if not aBoolValue then print('twas false') end --- 'or' and 'and' are short-circuited. This is similar to the a?b:c operator --- in C/js: +-- 'or' and 'and' are short-circuited. +-- This is similar to the a?b:c operator in C/js: ans = aBoolValue and 'yes' or 'no' --> 'no' --- BEWARE: this only acts as a ternary if the value returned when the condition --- evaluates to true is not `false` or Nil -iAmNotFalse = (not aBoolValue) and false or true --> true -iAmAlsoNotFalse = (not aBoolValue) and true or false --> true - karlSum = 0 for i = 1, 100 do -- The range includes both ends. karlSum = karlSum + i @@ -84,19 +81,20 @@ repeat num = num - 1 until num == 0 --------------------------------------------------------------------------------- + +---------------------------------------------------- -- 2. Functions. --------------------------------------------------------------------------------- +---------------------------------------------------- function fib(n) - if n < 2 then return n end + if n < 2 then return 1 end return fib(n - 2) + fib(n - 1) end -- Closures and anonymous functions are ok: function adder(x) - -- The returned function is created when adder is called, and remembers the - -- value of x: + -- The returned function is created when adder is + -- called, and remembers the value of x: return function (y) return x + y end end a1 = adder(9) @@ -104,9 +102,10 @@ a2 = adder(36) print(a1(16)) --> 25 print(a2(64)) --> 100 --- Returns, func calls, and assignments all work with lists that may be --- mismatched in length. Unmatched receivers are nil; unmatched senders are --- discarded. +-- Returns, func calls, and assignments all work +-- with lists that may be mismatched in length. +-- Unmatched receivers are nil; +-- unmatched senders are discarded. x, y, z = 1, 2, 3, 4 -- Now x = 1, y = 2, z = 3, and 4 is thrown away. @@ -119,15 +118,13 @@ end x, y = bar('zaphod') --> prints "zaphod nil nil" -- Now x = 4, y = 8, values 15..42 are discarded. --- Functions are first-class, may be local/global. These are the same: +-- Functions are first-class, may be local/global. +-- These are the same: function f(x) return x * x end f = function (x) return x * x end -- And so are these: local function g(x) return math.sin(x) end -local g = function(x) return math.sin(x) end --- Equivalent to local function g(x)..., except referring to g in the function --- body won't work as expected. local g; g = function (x) return math.sin(x) end -- the 'local g' decl makes g-self-references ok. @@ -136,16 +133,15 @@ local g; g = function (x) return math.sin(x) end -- Calls with one string param don't need parens: print 'hello' -- Works fine. --- Calls with one table param don't need parens either (more on tables below): -print {} -- Works fine too. --------------------------------------------------------------------------------- +---------------------------------------------------- -- 3. Tables. --------------------------------------------------------------------------------- +---------------------------------------------------- --- Tables = Lua's only compound data structure; they are associative arrays. --- Similar to php arrays or js objects, they are hash-lookup dicts that can --- also be used as lists. +-- Tables = Lua's only compound data structure; +-- they are associative arrays. +-- Similar to php arrays or js objects, they are +-- hash-lookup dicts that can also be used as lists. -- Using tables as dictionaries / maps: @@ -161,13 +157,14 @@ t.key2 = nil -- Removes key2 from the table. u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} print(u[6.28]) -- prints "tau" --- Key matching is basically by value for numbers and strings, but by identity --- for tables. +-- Key matching is basically by value for numbers +-- and strings, but by identity for tables. a = u['@!#'] -- Now a = 'qbert'. b = u[{}] -- We might expect 1729, but it's nil: --- b = nil since the lookup fails. It fails because the key we used is not the --- same object as the one used to store the original value. So strings & --- numbers are more portable keys. +-- b = nil since the lookup fails. It fails +-- because the key we used is not the same object +-- as the one used to store the original value. So +-- strings & numbers are more portable keys. -- A one-table-param function call needs no parens: function h(x) print(x.key1) end @@ -187,15 +184,16 @@ v = {'value1', 'value2', 1.21, 'gigawatts'} for i = 1, #v do -- #v is the size of v for lists. print(v[i]) -- Indices start at 1 !! SO CRAZY! end --- A 'list' is not a real type. v is just a table with consecutive integer --- keys, treated as a list. +-- A 'list' is not a real type. v is just a table +-- with consecutive integer keys, treated as a list. --------------------------------------------------------------------------------- +---------------------------------------------------- -- 3.1 Metatables and metamethods. --------------------------------------------------------------------------------- +---------------------------------------------------- --- A table can have a metatable that gives the table operator-overloadish --- behaviour. Later we'll see how metatables support js-prototype behaviour. +-- A table can have a metatable that gives the table +-- operator-overloadish behavior. Later we'll see +-- how metatables support js-prototypey behavior. f1 = {a = 1, b = 2} -- Represents the fraction a/b. f2 = {a = 2, b = 3} @@ -205,7 +203,7 @@ f2 = {a = 2, b = 3} metafraction = {} function metafraction.__add(f1, f2) - local sum = {} + sum = {} sum.b = f1.b * f2.b sum.a = f1.a * f2.b + f2.a * f1.b return sum @@ -216,9 +214,10 @@ setmetatable(f2, metafraction) s = f1 + f2 -- call __add(f1, f2) on f1's metatable --- f1, f2 have no key for their metatable, unlike prototypes in js, so you must --- retrieve it as in getmetatable(f1). The metatable is a normal table with --- keys that Lua knows about, like __add. +-- f1, f2 have no key for their metatable, unlike +-- prototypes in js, so you must retrieve it as in +-- getmetatable(f1). The metatable is a normal table +-- with keys that Lua knows about, like __add. -- But the next line fails since s has no metatable: -- t = s + s @@ -230,12 +229,11 @@ myFavs = {food = 'pizza'} setmetatable(myFavs, {__index = defaultFavs}) eatenBy = myFavs.animal -- works! thanks, metatable --------------------------------------------------------------------------------- --- Direct table lookups that fail will retry using the metatable's __index --- value, and this recurses. +-- Direct table lookups that fail will retry using +-- the metatable's __index value, and this recurses. --- An __index value can also be a function(tbl, key) for more customized --- lookups. +-- An __index value can also be a function(tbl, key) +-- for more customized lookups. -- Values of __index,add, .. are called metamethods. -- Full list. Here a is a table with the metamethod. @@ -256,19 +254,19 @@ eatenBy = myFavs.animal -- works! thanks, metatable -- __newindex(a, b, c) for a.b = c -- __call(a, ...) for a(...) --------------------------------------------------------------------------------- +---------------------------------------------------- -- 3.2 Class-like tables and inheritance. --------------------------------------------------------------------------------- +---------------------------------------------------- --- Classes aren't built in; there are different ways to make them using --- tables and metatables. +-- Classes aren't built in; there are different ways +-- to make them using tables and metatables. -- Explanation for this example is below it. Dog = {} -- 1. function Dog:new() -- 2. - local newObj = {sound = 'woof'} -- 3. + newObj = {sound = 'woof'} -- 3. self.__index = self -- 4. return setmetatable(newObj, self) -- 5. end @@ -281,59 +279,62 @@ mrDog = Dog:new() -- 7. mrDog:makeSound() -- 'I say woof' -- 8. -- 1. Dog acts like a class; it's really a table. --- 2. "function tablename:fn(...)" is the same as --- "function tablename.fn(self, ...)", The : just adds a first arg called --- self. Read 7 & 8 below for how self gets its value. +-- 2. function tablename:fn(...) is the same as +-- function tablename.fn(self, ...) +-- The : just adds a first arg called self. +-- Read 7 & 8 below for how self gets its value. -- 3. newObj will be an instance of class Dog. --- 4. "self" is the class being instantiated. Often self = Dog, but inheritance --- can change it. newObj gets self's functions when we set both newObj's --- metatable and self's __index to self. +-- 4. self = the class being instantiated. Often +-- self = Dog, but inheritance can change it. +-- newObj gets self's functions when we set both +-- newObj's metatable and self's __index to self. -- 5. Reminder: setmetatable returns its first arg. --- 6. The : works as in 2, but this time we expect self to be an instance --- instead of a class. +-- 6. The : works as in 2, but this time we expect +-- self to be an instance instead of a class. -- 7. Same as Dog.new(Dog), so self = Dog in new(). -- 8. Same as mrDog.makeSound(mrDog); self = mrDog. --------------------------------------------------------------------------------- +---------------------------------------------------- -- Inheritance example: LoudDog = Dog:new() -- 1. function LoudDog:makeSound() - local s = self.sound .. ' ' -- 2. + s = self.sound .. ' ' -- 2. print(s .. s .. s) end seymour = LoudDog:new() -- 3. seymour:makeSound() -- 'woof woof woof' -- 4. --------------------------------------------------------------------------------- -- 1. LoudDog gets Dog's methods and variables. -- 2. self has a 'sound' key from new(), see 3. --- 3. Same as "LoudDog.new(LoudDog)", and converted to "Dog.new(LoudDog)" as --- LoudDog has no 'new' key, but does have "__index = Dog" on its metatable. --- Result: seymour's metatable is LoudDog, and "LoudDog.__index = Dog". So --- seymour.key will equal seymour.key, LoudDog.key, Dog.key, whichever +-- 3. Same as LoudDog.new(LoudDog), and converted to +-- Dog.new(LoudDog) as LoudDog has no 'new' key, +-- but does have __index = Dog on its metatable. +-- Result: seymour's metatable is LoudDog, and +-- LoudDog.__index = LoudDog. So seymour.key will +-- = seymour.key, LoudDog.key, Dog.key, whichever -- table is the first with the given key. --- 4. The 'makeSound' key is found in LoudDog; this is the same as --- "LoudDog.makeSound(seymour)". +-- 4. The 'makeSound' key is found in LoudDog; this +-- is the same as LoudDog.makeSound(seymour). -- If needed, a subclass's new() is like the base's: function LoudDog:new() - local newObj = {} + newObj = {} -- set up newObj self.__index = self return setmetatable(newObj, self) end --------------------------------------------------------------------------------- +---------------------------------------------------- -- 4. Modules. --------------------------------------------------------------------------------- +---------------------------------------------------- ---[[ I'm commenting out this section so the rest of this script remains --- runnable. +--[[ I'm commenting out this section so the rest of +-- this script remains runnable. ``` ```lua @@ -359,8 +360,8 @@ local mod = require('mod') -- Run the file mod.lua. local mod = (function () <contents of mod.lua> end)() --- It's like mod.lua is a function body, so that locals inside mod.lua are --- invisible outside it. +-- It's like mod.lua is a function body, so that +-- locals inside mod.lua are invisible outside it. -- This works because mod here = M in mod.lua: mod.sayHello() -- Says hello to Hrunkner. @@ -368,19 +369,19 @@ mod.sayHello() -- Says hello to Hrunkner. -- This is wrong; sayMyName only exists in mod.lua: mod.sayMyName() -- error --- require's return values are cached so a file is run at most once, even when --- require'd many times. +-- require's return values are cached so a file is +-- run at most once, even when require'd many times. -- Suppose mod2.lua contains "print('Hi!')". local a = require('mod2') -- Prints Hi! local b = require('mod2') -- Doesn't print; a=b. -- dofile is like require without caching: -dofile('mod2') --> Hi! -dofile('mod2') --> Hi! (runs again, unlike require) +dofile('mod2.lua') --> Hi! +dofile('mod2.lua') --> Hi! (runs it again) -- loadfile loads a lua file but doesn't run it yet. -f = loadfile('mod2') -- Calling f() runs mod2.lua. +f = loadfile('mod2.lua') -- Call f() to run it. -- loadstring is loadfile for strings. g = loadstring('print(343)') -- Returns a function. diff --git a/m.html.markdown b/m.html.markdown index d0879ab6..96828ae5 100644 --- a/m.html.markdown +++ b/m.html.markdown @@ -125,7 +125,7 @@ w !,^cars w !,^cars("Tesla") ; null value - there's no value assigned to this node but it has children w !,^cars("Tesla",1,"Name") -; Model X +; Model 3 ``` Arrays are automatically sorted in order. Take advantage of the built-in sorting by setting your value of interest as the last child subscript of an array rather than its value. diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 74eb7993..b631df0a 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -161,7 +161,7 @@ let my_lambda = fun x -> x * x ;; (*** Operators ***) -(* There is little distintion between operators and functions. +(* There is little distinction between operators and functions. Every operator can be called as a function. *) (+) 3 4 (* Same as 3 + 4 *) diff --git a/pascal.html.markdown b/pascal.html.markdown index 28dcc10f..9fb51c3b 100644 --- a/pascal.html.markdown +++ b/pascal.html.markdown @@ -66,7 +66,7 @@ program Learn_More; const PI = 3.141592654; - GNU = 'GNU's Not Unix'; + GNU = 'GNU''s Not Unix'; // constants are conventionally named using CAPS // their values are fixed and cannot be changed during runtime // holds any standard data type (integer, real, boolean, char, string) diff --git a/perl6-pod.html.markdown b/perl6-pod.html.markdown new file mode 100644 index 00000000..80a501b8 --- /dev/null +++ b/perl6-pod.html.markdown @@ -0,0 +1,622 @@ +--- +language: Pod +contributors: + - ["Luis F. Uceta", "https://uzluisf.gitlab.io/"] +filename: learnpod.pod6 +--- + +Pod is an easy-to-use and purely descriptive mark-up language, +with no presentational components. Besides its use for documenting +Raku Perl 6 programs and modules, Pod can be utilized to write language +documentation, blogs, and other types of document composition as well. + +Pod documents can be easily converted to HTML and many other formats +(e.g., Markdown, Latex, plain text, etc.) by using the corresponding +variant of the `Pod::To` modules (e.g. `Pod::To::HTML` for HTML conversion). + +- [General Info](#general-info) +- [Pod Basics](#pod-basics) + - [Basic Text Formatting](#basic-text-formatting) + - [Headings](#headings) + - [Ordinary Paragraphs](#ordinary-paragraphs) + - [Lists](#lists) + - [Code Blocks](#code-blocks) + - [Comments](#comments) + - [Links](#links) + - [Tables](#tables) +- [Block Structures](#block-structures) + - [Abbreviated Blocks](#abbreviated-blocks) + - [Delimited Blocks](#delimited-blocks) + - [Paragraph Blocks](#paragraph-blocks) +- [Configuration Data](#configuration-data) + - [Standard Configuration Options](#standard-configuration-options) + - [Block Pre-configuration](#block-pre-configuration) +- [Semantic Blocks](#semantic-blocks) +- [Miscellaneous](#miscellaneous) + - [Notes](#notes) + - [Keyboard Input](#keyboard-input) + - [Terminal Output](#terminal-output) + - [Unicode](#unicode) +- [Rendering Pod](#rendering-pod) +- [Accessing Pod](#accessing-pod) + +## General Info + +Every Pod document has to begin with `=begin pod` and end with `=end pod`. +Everything between these two delimiters will be processed and used to +generate documentation. + +``` +=begin pod + +A very simple Raku Perl 6 Pod document. All the other directives go here! + +=end pod +``` + +Pod documents usually coexist with Raku Perl 6 code. If by themselves, +Pod files often have the `.pod6` suffix. Moving forward, it's assumed that +the constructs being discussed are surrounded by the `=begin pod ... =end pod` +directives. + +## Pod Basics + +### Basic Text Formatting + +Text can be easily styled as bold, italic, underlined or verbatim (for code +formatting) using the following formatting codes: `B<>`, `I<>`, `U<>` +and `C<>`. + +``` +B<This text is in Bold.> + +I<This text is in Italics.> + +U<This text is Underlined.> + +The function C<sub sum { $^x + $^y}> is treated as verbatim. +``` + +There are more formatting codes (e.g., `L<>`, `T<>`, etc.) but they'll be +discussed later throughout the document. You'll recognize them because they're +just a single capital letter followed immediately by a set of single or double +angle brackets. The Unicode variant («») of the angle brackets can also be +used. + +### Headings + +Headings are created by using the `=headN` directive where `N` is the +heading level. + +``` +=head1 This is level 1 +=head2 This is level 2 +=head3 This is level 3 +=head4 This is level 4 +=head5 This is level 5 +=head6 This is level 6 +``` + +### Ordinary Paragraphs + +Ordinary paragraphs consist of one or more adjacent lines of text, each of +which starts with a non-whitespace character. Any paragraph is terminated +by the first blank line or block directive. + +``` +=head1 First level heading block + +=head2 Paragraph 1 + +This is an ordinary paragraph. Its text will be squeezed and +short lines filled. It is terminated by the first blank line. + +=head2 Paragraph 2 + +This is another ordinary paragraph albeit shorter. +``` + +Alternatively, the `=para` directive can be used to explicitly mark adjacent +lines of text as a paragraph. + +``` +=head1 First level heading block + +=head2 Paragraph 1 + +=para +This is an ordinary paragraph. Its text will be squeezed and +short lines filled. It is terminated by the first blank line. + +=head2 Paragraph 2 + +=para +This is another ordinary paragraph albeit shorter. +``` + +### Lists + +Unordered lists can be created using the `=item` directive. + +``` +=item Item +=item Item +=item Another item +``` + +Sublists are achieved with items at each level specified using the `=item1`, +`=item2`, `=item3`, `...`, `=itemN` etc. directives. The `=item` directive +defaults to `=item1`. + +``` +=item1 Item one +=item1 Item two +=item1 Item three + =item2 Sub-item + =item2 Sub-item +=item1 Item four +``` + +Definition lists that define terms or commands use the `=defn` directive. +This is equivalent to the `<dl>` element in HTML. + +``` +=defn Beast of Bodmin +A large feline inhabiting Bodmin Moor. + +=defn Morgawr +A sea serpent. + +=defn Owlman +A giant owl-like creature. +``` + +### Code Blocks + +A code block is created (which uses the HTML `<code>` element) by starting each +line with one or more whitespace characters. + +``` + #`( this is comment ) + my $sum = -> $x, $y { $x + $y } + say $sum(12, 5); +``` + +As shown in the [Basic Text Formatting](#basic-text-formatting) section, +inline code can be created using the `C<>` code. + +``` +In Raku Perl 6, there are several functions/methods to output text. Some of them +are C<print>, C<put> and C<say>. +``` + +### Comments + +Although Pod blocks are ignored by the Raku Perl 6 compiler, everything +indentified as a Pod block will be read and interpreted by Pod renderers. In +order to prevent Pod blocks from being rendered by any renderer, use the +`=comment` directive. + +``` +=comment Add more here about the algorithm. + +=comment Pod comments are great for documenting the documentation. +``` + +To create inline comments, use the `Z<>` code. + +``` +Pod is awesome Z<Of course it is!>. And Raku Perl 6 too! +``` + +Given that the Perl interpreter never executes embedded Pod blocks, +comment blocks can also be used as an alternative form of nestable block +comments in Raku Perl 6. + +### Links + +Creating links in Pod is quite easy and is done by enclosing them in +a `L<>` code. The general format is `L<Label|Url>` with `Label` +being optional. + +``` +Raku Perl 6 homepage is L<https://perl6.org>. +L<Click me!|http://link.org/>. +``` + +Relative paths work too. + +``` +L<Go to music|/music/>. +``` + +Linking to a section in the same document works as well. + +``` +L<Link to Headings|#Headings> +``` + +### Tables + +The Pod specifications are not completely handled properly yet and this +includes the handling of table. For simplicity's sake, only one way of +constructing tables is shown here. To learn about good practices and see +examples of both good and bad tables, please visit +<https://docs.perl6.org/language/tables>. + +``` +=begin table +Option | Description +============|================ +data | path to data files. +engine | engine to be used for processing templates. +ext | extension to be used for dest files. +=end table +``` + +## Block Structures + +As mentioned earlier, Pod documents are specified using directives, which are +used to delimit blocks of textual content and declare optional +[configuration information](#configuration-data). Every directive starts with +an equals sign (`=`) in the first column. The content of a document is +specified within one or more blocks. Every Pod block may be declared in any of +three equivalent forms: delimited style, paragraph style, or abbreviated style. + +Up to this point, we have only used the abbreviated style for the block +types (e.g., `=head1`, `=para`, `=comment`, `=item`, etc). + +### Abbreviated Blocks + +Abbreviated blocks are introduced by an `=` sign in the first column, which +is followed immediately by the `typename` of the block and then the content. +The rest of the line is treated as block data, rather than as configuration. +The content terminates at the next Pod directive or the first blank line +(which is not part of the block data). The general syntax is + +``` +=BLOCK_TYPE BLOCK_DATA +``` +For example: + +``` +=head1 Top level heading +``` + +### Delimited Blocks + +Delimited blocks are bounded by `=begin` and `=end` markers, both of which are +followed by a valid Pod identifier, which is the `typename` of the block. +The general syntax is + +``` +=begin BLOCK_TYPE +BLOCK_DATA +=end BLOCK_TYPE +``` + +For example: + +``` +=begin head1 +Top level heading +=end head1 +``` + +This type of blocks is useful for creating headings, list items, code blocks, +etc. with multiple paragraphs. For example, + +* a multiline item of a list + +``` +=begin item +This is a paragraph in list item. + +This is another paragraph in the same list item. +=end item +``` + +* a code block + +``` +=begin code +#`( +A non-efficient recursive implementation of a power function using multi subs. +) + +multi pow( Real $base, 0 ) { 1 } + +multi pow( Real $base, Int $exp where * ≥ 0) { + $base * pow($base, $exp - 1) +} + +multi pow( Real $base ) { + pow($base, 2) +} + +say pow(3, 0); #=> 1 +say pow(4.2, 2); #=> 17.64 +say pow(6); #=> 36 +=end code +``` + +### Paragraph Blocks + +Paragraph blocks are introduced by a `=for` marker and terminated by +the next Pod directive or the first blank line (which is not considered to +be part of the block's contents). The `=for` marker is followed by the +`typename` of the block. The general syntax is + +``` +=for BLOCK_TYPE +BLOCK DATA +``` + +For example: + +``` +=for head1 +Top level heading +``` + +## Configuration Data + +Except for abbreviated blocks, both delimited blocks and paragraph +blocks can be supplied with configuration information about their +contents right after the `typename` of the block. Thus the following +are more general syntaxes for these blocks: + +* Delimited blocks + +``` +=begin BLOCK_TYPE OPTIONAL_CONFIG_INFO += ADDITIONAL_CONFIG_INFO +BLOCK_DATA +=end BLOCK_TYPE +``` + +* Paragraph blocks + +``` +=for BLOCK_TYPE OPTIONAL_CONFIG_INFO += ADDITIONAL_CONFIG_INFO +BLOCK DATA +``` + +The configuration information is provided in a format akin to the +["colon pair"](https://docs.perl6.org/language/glossary#index-entry-Colon_Pair) +syntax in Raku Perl 6. The following table is a simplified version of the +different ways in which configuration info can be supplied. Please go to +<https://docs.perl6.org/language/pod#Configuration_information> for a more +thorough treatment of the subject. + +| Value | Specify with... | Example | +| :-------- | :------ | :------ | +| List | :key($elem1, $elem2, ...) | :tags('Pod', 'Perl6') | +| Hash | :key{$key1 => $value1, ...} | :feeds{url => 'perl6.org'} | +| Boolean | :key/:key(True) | :skip-test(True) | +| Boolean | :!key/:key(False) | :!skip-test | +| String | :key('string') | :nonexec-reason('SyntaxError') | +| Int | :key(2) | :post-number(6) | + + +### Standard Configuration Options + +Pod provides a small number of standard configuration options that can +be applied uniformly to built-in block types. Some of them are: + +* `:numbered` + +This option specifies that the block is to be numbered. The most common +use of this option is to create numbered headings and ordered lists, but it +can be applied to any block. + +For example: + +``` +=for head1 :numbered +The Problem +=for head1 :numbered +The Solution +=for head2 :numbered +Analysis +=for head3 :numbered +Overview +``` + +* `:allow` + +The value of the `:allow` option must be a list of the (single-letter) names +of one or more formatting codes. Those codes will then remain active inside +the code block. The option is most often used on `=code` blocks to allow +mark-up within those otherwise verbatim blocks, though it can be used in any +block that contains verbatim text. + +Given the following snippet: + +``` +=begin code :allow('B', 'I') +B<sub> greet( $name ) { + B<say> "Hello, $nameI<!>"; +} +=end code +``` + +we get the following output: + +<pre><strong>sub</strong> greet( $name ) { + <strong>say</strong> "Hello, $name<em>!</em>"; +} +</pre> + +This is highly dependent on the format output. For example, while this works +when Pod is converted to HTML, it might not be preserved when converted +to Markdown. + +### Block Pre-configuration + +The `=config` directive allows you to prespecify standard configuration +information that is applied to every block of a particular type. +The general syntax for configuration directives is: + +``` +=config BLOCK_TYPE CONFIG OPTIONS += ADDITIONAL_CONFIG_INFO +``` + +For example, to specify that every heading level 1 be numbered, bold +and underlined, you preconfigure the `=head1` as follows: + +``` +=config head1 :formatted('B', 'U') :numbered +``` + +## Semantic Blocks + +All uppercase block typenames are reserved for specifying standard +documentation, publishing, source components, or meta-information. +Some of them are: + +``` +=NAME +=AUTHOR +=VERSION +=CREATED +=SYNOPSIS +=DESCRIPTION +=USAGE +``` + +Most of these blocks would typically be used in their full +delimited forms. For example, + +``` +=NAME B<Doc::Magic> + +=begin DESCRIPTION +This module helps you generate documentation automagically. +Not source code needed! Most of it is outsourced from a black hole. +=end DESCRIPTION + +=begin SYNOPSIS +=begin code + use Doc::Magic; + + my Doc::Magic $doc .= new(); + + my $result = $doc.create-documentation($fh); +=end code +=end SYNOPSIS + +=AUTHOR Authorius Docus +=VERSION 42 +``` + +## Miscellaneous + +### Notes + +Notes are rendered as footnotes and created by enclosing a note in a +`N<>` code. + +``` +In addition, the language is also multi-paradigmatic N<According to Wikipedia, +this means that it supports procedural, object-oriented, and functional +programming.> +``` + +### Keyboard Input + +To flag text as keyboard input enclose it in a `K<>` code. + +``` +Enter your name K<John Doe> +``` + +### Terminal Output + +To flag text as terminal output enclose it in `T<>` code. + +``` +Hello, T<John Doe> +``` + +### Unicode + +To include Unicode code points or HTML5 character references in +a Pod document, enclose them in a `E<>` code. + +For example: + +``` +Raku Perl 6 makes considerable use of the E<171> and E<187> characters. +Raku Perl 6 makes considerable use of the E<laquo> and E<raquo> characters. +``` + +is rendered as: + +Raku Perl 6 makes considerable use of the « and » characters. +Raku Perl 6 makes considerable use of the « and » characters. + +## Rendering Pod + +To generate any output (i.e., Markdown, HTML, Text, etc.), you need to +have the Raku Perl 6 compiler installed. In addition, you must install +a module (e.g., `Pod::To::Markdown`, `Pod::To::HTML`, `Pod::To::Text`, etc.) +that generates your desired output from Pod. + +For instructions about installing Raku Perl 6, +[look here](https://perl6.org/downloads/). + +Run the following command to generate a certain output: + +``` +perl6 --doc=TARGET input.pod6 > output.html +``` + +with `TARGET` being `Markdown`, `HTML`, `Text`, etc. Thus to generate +Markdown from Pod, run this: + +``` +perl6 --doc=Markdown input.pod6 > output.html +``` + +## Accessing Pod + +In order to access Pod documentation from within a Raku Perl 6 program, +it is required to use the special `=` twigil (e.g., `$=pod`, `$=SYNOPSIS`,etc). + +The `$=` construct provides the introspection over the Pod structure, +producing a `Pod::Block` tree root from which it is possible to access +the whole structure of the Pod document. + +If we place the following piece of Raku Perl 6 code and the Pod documentation +in the section [Semantic blocks](#semantic-blocks) in the same file: + +``` +my %used-directives; +for $=pod -> $pod-item { + for $pod-item.contents -> $pod-block { + next unless $pod-block ~~ Pod::Block::Named; + %used-directives{$pod-block.name} = True; + } +} + +say %used-directives.keys.join("\n"); +``` + +we get the following output: + +``` +SYNOPSIS +NAME +VERSION +AUTHOR +DESCRIPTION +``` + +## Additional Information + +* <https://docs.perl6.org/language/pod> for the Pod documentation. +* <https://docs.perl6.org/language/tables> for advices about Pod tables. +* <https://design.perl6.org/S26.html> for the Pod specification. diff --git a/perl6.html.markdown b/perl6.html.markdown index 7c776db4..cb64b646 100644 --- a/perl6.html.markdown +++ b/perl6.html.markdown @@ -13,24 +13,28 @@ least the next hundred years. The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on the JVM and [the MoarVM](http://moarvm.com). -Meta-note : double pound signs (##) are used to indicate paragraphs, while -single pound signs (#) indicate notes. +Meta-note: double pound signs (`##`) are used to indicate paragraphs, +while single pound signs (`#`) indicate notes. `#=>` represents the output of a command. ```perl6 -# Single line comment start with a pound +# Single line comments start with a pound sign. -#`( - Multiline comments use #` and a quoting construct. +#`( Multiline comments use #` and a quoting construct. (), [], {}, 「」, etc, will work. ) + +# Use the same syntax for multiline comments to embed comments. +for #`(each element in) @array { + put #`(or print element) $_ #`(with newline); +} ``` ## Variables ```perl6 -## In Perl 6, you declare a lexical variable using `my` +## In Perl 6, you declare a lexical variable using the `my` keyword: my $variable; ## Perl 6 has 3 basic types of variables: scalars, arrays, and hashes. ``` @@ -38,79 +42,81 @@ my $variable; ### Scalars ```perl6 -# Scalars represent a single value. They start with a `$` - +# Scalars represent a single value. They start with the `$` sigil: my $str = 'String'; -# double quotes allow for interpolation (which we'll see later): + +# Double quotes allow for interpolation (which we'll see later): my $str2 = "String"; ## Variable names can contain but not end with simple quotes and dashes, -## and can contain (and end with) underscores : -my $weird'variable-name_ = 5; # works ! +## and can contain (and end with) underscores: +my $person's-belongings = 'towel'; # this works! -my $bool = True; # `True` and `False` are Perl 6's boolean values. -my $inverse = !$bool; # You can invert a bool with the prefix `!` operator -my $forced-bool = so $str; # And you can use the prefix `so` operator - # which turns its operand into a Bool +my $bool = True; # `True` and `False` are Perl 6's boolean values. +my $inverse = !$bool; # Invert a bool with the prefix `!` operator. +my $forced-bool = so $str; # And you can use the prefix `so` operator +$forced-bool = ?$str; # to turn its operand into a Bool. Or use `?`. ``` ### Arrays and Lists ```perl6 -## Arrays represent multiple values. Their name start with `@`. -## Lists are similar but are an immutable type. +## Arrays represent multiple values. An array variable starts with the `@` +## sigil. Unlike lists, from which arrays inherit, arrays are mutable. my @array = 'a', 'b', 'c'; -# equivalent to : +# equivalent to: my @letters = <a b c>; # array of words, delimited by space. # Similar to perl5's qw, or Ruby's %w. -my @array = 1, 2, 3; +@array = 1, 2, 3; -say @array[2]; # Array indices start at 0 -- This is the third element +say @array[2]; # Array indices start at 0. Here the third element + # is being accessed. -say "Interpolate all elements of an array using [] : @array[]"; -#=> Interpolate all elements of an array using [] : 1 2 3 +say "Interpolate an array using []: @array[]"; +#=> Interpolate an array using []: 1 2 3 -@array[0] = -1; # Assign a new value to an array index -@array[0, 1] = 5, 6; # Assign multiple values +@array[0] = -1; # Assigning a new value to an array index +@array[0, 1] = 5, 6; # Assigning multiple values my @keys = 0, 2; @array[@keys] = @letters; # Assignment using an array containing index values -say @array; #=> a 6 b +say @array; #=> a 6 b ``` ### Hashes, or key-value Pairs. ```perl6 -## Hashes are pairs of keys and values. -## You can construct a Pair object using the syntax `Key => Value`. -## Hash tables are very fast for lookup, and are stored unordered. -## Keep in mind that keys get "flattened" in hash context, and any duplicated -## keys are deduplicated. -my %hash = 1 => 2, - 3 => 4; -my %hash = foo => "bar", # keys get auto-quoted - "some other" => "value", # trailing commas are okay - ; +## Hashes are pairs of keys and values. You can construct a `Pair` object +## using the syntax `Key => Value`. Hash tables are very fast for lookup, +## and are stored unordered. Keep in mind that keys get "flattened" in hash +## context, and any duplicated keys are deduplicated. +my %hash = 'a' => 1, 'b' => 2; + +%hash = a => 1, # keys get auto-quoted when => (fat comma) is used. + b => 2, # Trailing commas are okay. +; ## Even though hashes are internally stored differently than arrays, ## Perl 6 allows you to easily create a hash from an even numbered array: -my %hash = <key1 value1 key2 value2>; - -my %hash = key1 => 'value1', key2 => 'value2'; # same result as above - -## You can also use the "colon pair" syntax: -## (especially handy for named parameters that you'll see later) -my %hash = :w(1), # equivalent to `w => 1` - # this is useful for the `True` shortcut: - :truey, # equivalent to `:truey(True)`, or `truey => True` - # and for the `False` one: - :!falsey, # equivalent to `:falsey(False)`, or `falsey => False` - ; - -say %hash{'key1'}; # You can use {} to get the value from a key -say %hash<key2>; # If it's a string, you can actually use <> - # (`{key1}` doesn't work, as Perl6 doesn't have barewords) +%hash = <key1 value1 key2 value2>; # Or: +%hash = "key1", "value1", "key2", "value2"; + +%hash = key1 => 'value1', key2 => 'value2'; # same result as above + +## You can also use the "colon pair" syntax. This syntax is especially +## handy for named parameters that you'll see later. +%hash = :w(1), # equivalent to `w => 1` + :truey, # equivalent to `:truey(True)` or `truey => True` + :!falsey, # equivalent to `:falsey(False)` or `falsey => False` +; +## The :truey and :!falsey constructs are known as the +## `True` and `False` shortcuts respectively. + +say %hash{'key1'}; # You can use {} to get the value from a key. +say %hash<key2>; # If it's a string without spaces, you can actually use + # <> (quote-words operator). `{key1}` doesn't work, + # as Perl6 doesn't have barewords. ``` ## Subs @@ -120,112 +126,112 @@ say %hash<key2>; # If it's a string, you can actually use <> ## created with the `sub` keyword. sub say-hello { say "Hello, world" } -## You can provide (typed) arguments. -## If specified, the type will be checked at compile-time if possible, -## otherwise at runtime. -sub say-hello-to(Str $name) { +## You can provide (typed) arguments. If specified, the type will be checked +## at compile-time if possible, otherwise at runtime. +sub say-hello-to( Str $name ) { say "Hello, $name !"; } -## A sub returns the last value of the block. -sub return-value { - 5; -} -say return-value; # prints 5 -sub return-empty { -} -say return-empty; # prints Nil +## A sub returns the last value of the block. Similarly, the semicolon in +## the last can be omitted. +sub return-value { 5 } +say return-value; # prints 5 -## Some control flow structures produce a value, like if: +sub return-empty { } +say return-empty; # prints Nil + +## Some control flow structures produce a value, like `if`: sub return-if { - if True { - "Truthy"; - } + if True { "Truthy" } } -say return-if; # prints Truthy +say return-if; # prints Truthy -## Some don't, like for: +## Some don't, like `for`: sub return-for { - for 1, 2, 3 { } + for 1, 2, 3 { 'Hi' } } -say return-for; # prints Nil +say return-for; # prints Nil -## A sub can have optional arguments: -sub with-optional($arg?) { # the "?" marks the argument optional - say "I might return `(Any)` (Perl's 'null'-like value) if I don't have - an argument passed, or I'll return my argument"; +## Positional arguments are required by default. To make them optional, use +## the `?` after the parameters' names. +sub with-optional( $arg? ) { + # This sub returns `(Any)` (Perl's null-like value) if + # no argument is passed. Otherwise, it returns its argument. $arg; } -with-optional; # returns Any -with-optional(); # returns Any -with-optional(1); # returns 1 +with-optional; # returns Any +with-optional(); # returns Any +with-optional(1); # returns 1 -## You can also give them a default value when they're not passed: -sub hello-to($name = "World") { - say "Hello, $name !"; +## You can also give them a default value when they're not passed. +## Required parameters must come before optional ones. +sub greeting( $name, $type = "Hello" ) { + say "$type, $name!"; } -hello-to; #=> Hello, World ! -hello-to(); #=> Hello, World ! -hello-to('You'); #=> Hello, You ! + +greeting("Althea"); #=> Hello, Althea! +greeting("Arthur", "Good morning"); #=> Good morning, Arthur! ## You can also, by using a syntax akin to the one of hashes -## (yay unified syntax !), pass *named* arguments to a `sub`. -## They're optional, and will default to "Any". -sub with-named($normal-arg, :$named) { - say $normal-arg + $named; +## (yay unified syntax !), pass *named* arguments to a `sub`. They're +## optional, and will default to "Any". +sub with-named( $normal-arg, :$named ) { + say $normal-arg + $named; } with-named(1, named => 6); #=> 7 -## There's one gotcha to be aware of, here: -## If you quote your key, Perl 6 won't be able to see it at compile time, -## and you'll have a single Pair object as a positional parameter, -## which means this fails: -with-named(1, 'named' => 6); -with-named(2, :named(5)); #=> 7 +## There's one gotcha to be aware of, here: If you quote your key, Perl 6 +## won't be able to see it at compile time, and you'll have a single `Pair` +## object as a positional parameter, which means +## `with-named(1, 'named' => 6);` fails. + +with-named(2, :named(5)); #=> 7 -## To make a named argument mandatory, you can use `?`'s inverse, `!` -sub with-mandatory-named(:$str!) { - say "$str !"; +## To make a named argument mandatory, you can append `!` to the parameter, +## which is the inverse of `?`: +sub with-mandatory-named( :$str! ) { + say "$str!"; } -with-mandatory-named(str => "My String"); #=> My String ! -with-mandatory-named; # run time error: "Required named parameter not passed" -with-mandatory-named(3);# run time error:"Too many positional parameters passed" +with-mandatory-named(str => "My String"); #=> My String! +with-mandatory-named; # runtime error:"Required named parameter not passed" +with-mandatory-named(3);# runtime error:"Too many positional parameters passed" -## If a sub takes a named boolean argument ... -sub takes-a-bool($name, :$bool) { - say "$name takes $bool"; +## If a sub takes a named boolean argument... +sub takes-a-bool( $name, :$bool ) { + say "$name takes $bool"; } ## ... you can use the same "short boolean" hash syntax: -takes-a-bool('config', :bool); # config takes True -takes-a-bool('config', :!bool); # config takes False +takes-a-bool('config', :bool); #=> config takes True +takes-a-bool('config', :!bool); #=> config takes False -## You can also provide your named arguments with defaults: -sub named-def(:$def = 5) { - say $def; +## You can also provide your named arguments with default values: +sub named-def( :$def = 5 ) { + say $def; } -named-def; #=> 5 +named-def; #=> 5 named-def(def => 15); #=> 15 ## Since you can omit parenthesis to call a function with no arguments, -## you need "&" in the name to store `say-hello` in a variable. +## you need `&` in the name to store `say-hello` in a variable. This means +## `&say-hello` is a code object and not a subroutine call. my &s = &say-hello; -my &other-s = sub { say "Anonymous function !" } +my &other-s = sub { say "Anonymous function!" } -## A sub can have a "slurpy" parameter, or "doesn't-matter-how-many" -sub as-many($head, *@rest) { #`*@` (slurpy) will "take everything else" -## Note: you can have parameters *before* a slurpy one (like here), -## but not *after*. - say @rest.join(' / ') ~ " !"; +## A sub can have a "slurpy" parameter, or "doesn't-matter-how-many". For +## this, you must use `*@` (slurpy) which will "take everything else". You can +## have as many parameters *before* a slurpy one, but not *after*. +sub as-many($head, *@rest) { + say @rest.join(' / ') ~ " !"; } -say as-many('Happy', 'Happy', 'Birthday'); #=> Happy / Birthday ! - # Note that the splat (the *) did not - # consume the parameter before. +say as-many('Happy', 'Happy', 'Birthday');#=> Happy / Birthday ! + # Note that the splat (the *) did not + # consume the parameter before it. -## You can call a function with an array using the -## "argument list flattening" operator `|` -## (it's not actually the only role of this operator, but it's one of them) +## You can call a function with an array using the "argument list flattening" +## operator `|` (it's not actually the only role of this operator, +## but it's one of them). sub concat3($a, $b, $c) { - say "$a, $b, $c"; + say "$a, $b, $c"; } concat3(|@array); #=> a, b, c # `@array` got "flattened" as a part of the argument list @@ -234,159 +240,188 @@ concat3(|@array); #=> a, b, c ## Containers ```perl6 -## In Perl 6, values are actually stored in "containers". -## The assignment operator asks the container on the left to store the value on -## its right. When passed around, containers are marked as immutable. -## Which means that, in a function, you'll get an error if you try to -## mutate one of your arguments. -## If you really need to, you can ask for a mutable container using `is rw`: -sub mutate($n is rw) { - $n++; - say "\$n is now $n !"; +## In Perl 6, values are actually stored in "containers". The assignment +## operator asks the container on the left to store the value on its right. +## When passed around, containers are marked as immutable which means that, +## in a function, you'll get an error if you try to mutate one of your +## arguments. If you really need to, you can ask for a mutable container by +## using the `is rw` trait: +sub mutate( $n is rw ) { + $n++; } my $m = 42; -mutate $m; # $m is now 43 ! +mutate $m; #=> 43 +say $m; #=> 43 -## This works because we are passing the container $m to mutate. If we try -## to just pass a number instead of passing a variable it won't work because -## there is no container being passed and integers are immutable by themselves: +## This works because we are passing the container $m to the `mutate` sub. +## If we try to just pass a number instead of passing a variable it won't work +## because there is no container being passed and integers are immutable by +## themselves: mutate 42; # Parameter '$n' expected a writable container, but got Int value -## If what you want a copy instead, use `is copy`. +## Similar error would be obtained, if a bound variable is passed to +## to the subroutine: + +my $v := 50; # binding 50 to the variable $v +mutate $v; # Parameter '$n' expected a writable container, but got Int value + +## If what you want is a copy instead, use the `is copy` trait which will +## cause the argument to be copied and allow you to modify the argument +## inside the routine. ## A sub itself returns a container, which means it can be marked as rw: my $x = 42; sub x-store() is rw { $x } x-store() = 52; # in this case, the parentheses are mandatory # (else Perl 6 thinks `x-store` is an identifier) -say $x; #=> 52 +say $x; #=> 52 ``` ## Control Flow Structures + ### Conditionals ```perl6 ## - `if` ## Before talking about `if`, we need to know which values are "Truthy" -## (represent True), and which are "Falsey" (or "Falsy") -- represent False. -## Only these values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or -## `Int`) and of course False itself. -## Every other value is Truthy. +## (represent True), and which are "Falsey" (represent False). Only these +## values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or `Int`) and +## of course False itself. Any other value is Truthy. if True { - say "It's true !"; + say "It's true!"; } unless False { - say "It's not false !"; + say "It's not false!"; } -## As you can see, you don't need parentheses around conditions. -## However, you do need the brackets around the "body" block: -# if (true) say; # This doesn't work ! +## As you can see, you don't need parentheses around conditions. However, you +## do need the curly braces around the "body" block. For example, +## `if (true) say;` doesn't work. -## You can also use their postfix versions, with the keyword after: -say "Quite truthy" if True; +## You can also use their statement modifier (postfix) versions: +say "Quite truthy" if True; #=> Quite truthy +say "Quite falsey" unless False; #=> Quite falsey -## - Ternary conditional, "?? !!" (like `x ? y : z` in some other languages) -## returns $value-if-true if the condition is true and $value-if-false -## if it is false. -## my $result = $value condition ?? $value-if-true !! $value-if-false; +## - Ternary operator, "x ?? y !! z" +## This returns $value-if-true if the condition is true and $value-if-false +## if it is false. +## my $result = condition ?? $value-if-true !! $value-if-false; my $age = 30; say $age > 18 ?? "You are an adult" !! "You are under 18"; +#=> You are an adult ``` -### given/when, or switch +### given/when, or Perl 6's switch construct ```perl6 -## - `given`-`when` looks like other languages' `switch`, but is much more +## `given...when` looks like other languages' `switch`, but is much more ## powerful thanks to smart matching and Perl 6's "topic variable", $_. ## -## This variable contains the default argument of a block, -## a loop's current iteration (unless explicitly named), etc. +## The topic variable $_ contains the default argument of a block, a loop's +## current iteration (unless explicitly named), etc. ## ## `given` simply puts its argument into `$_` (like a block would do), ## and `when` compares it using the "smart matching" (`~~`) operator. ## ## Since other Perl 6 constructs use this variable (as said before, like `for`, -## blocks, etc), this means the powerful `when` is not only applicable along +## blocks, etc), this means the powerful `when` is not only applicable along ## with a `given`, but instead anywhere a `$_` exists. given "foo bar" { - say $_; #=> foo bar - when /foo/ { # Don't worry about smart matching yet – just know `when` uses it - # This is equivalent to `if $_ ~~ /foo/`. - say "Yay !"; - } - when $_.chars > 50 { # smart matching anything with True is True, - # i.e. (`$a ~~ True`) - # so you can also put "normal" conditionals. - # This `when` is equivalent to this `if`: - # if $_ ~~ ($_.chars > 50) {...} - # Which means: - # if $_.chars > 50 {...} - say "Quite a long string !"; - } - default { # same as `when *` (using the Whatever Star) - say "Something else" - } + say $_; #=> foo bar + when /foo/ { # Don't worry about smart matching yet. Just know + say "Yay !"; # `when` uses it. This is equivalent to `if $_ ~~ /foo/`. + + } + when $_.chars > 50 { # smart matching anything with True is True, + # i.e. (`$a ~~ True`) + # so you can also put "normal" conditionals. + # This `when` is equivalent to this `if`: + # `if $_ ~~ ($_.chars > 50) {...}` + # which means: `if $_.chars > 50 {...}` + say "Quite a long string !"; + } + default { # same as `when *` (using the Whatever Star) + say "Something else" + } } ``` ### Looping constructs ```perl6 -## - `loop` is an infinite loop if you don't pass it arguments, -## but can also be a C-style `for` loop: +## - `loop` is an infinite loop if you don't pass it arguments, but can also +## be a C-style `for` loop: loop { - say "This is an infinite loop !"; - last; # last breaks out of the loop, like the `break` keyword in other - # languages + say "This is an infinite loop !"; + last; # last breaks out of the loop, like + # the `break` keyword in other languages } loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` skips to the next iteration, like `continue` + next if $i == 3; # `next` skips to the next iteration, like `continue` # in other languages. Note that you can also use postfix # conditionals, loops, etc. - say "This is a C-style for loop !"; + say "This is a C-style for loop!"; } -## - `for` - Passes through an array +## - `for` - Iterating through an array + +my @array = 1, 2, 6, 7, 3; + +## Accessing the array's elements with the topic variable $_. +for @array { + say "I've got $_ !"; +} + +## Accessing the array's elements with a "pointy block", `->`. +## Here each element is read-only. for @array -> $variable { - say "I've got $variable !"; + say "I've got $variable !"; } -## As we saw with given, for's default "current iteration" variable is `$_`. -## That means you can use `when` in a `for` just like you were in a `given`. +## Accessing the array's elements with a "doubly pointy block", `<->`. +## Here each element is read-write so mutating `$variable` mutates +## that element in the array. +for @array <-> $variable { + say "I've got $variable !"; +} + +## As we saw with given, a for loop's default "current iteration" variable +## is `$_`. That means you can use `when` in a `for`loop just like you were +## able to in a `given`. for @array { - say "I've got $_"; + say "I've got $_"; - .say; # This is also allowed. - # A dot call with no "topic" (receiver) is sent to `$_` by default - $_.say; # the above and this are equivalent. + .say; # This is also allowed. A dot call with no "topic" (receiver) + # is sent to `$_` by default + $_.say; # This is equivalent to the above statement. } for @array { - # You can... - next if $_ == 3; # Skip to the next iteration (`continue` in C-like languages) - redo if $_ == 4; # Re-do the iteration, keeping the same topic variable (`$_`) - last if $_ == 5; # Or break out of a loop (like `break` in C-like languages) + # You can... + next if $_ == 3; # Skip to the next iteration (`continue` in C-like lang.) + redo if $_ == 4; # Re-do iteration, keeping the same topic variable (`$_`) + last if $_ == 5; # Or break out of loop (like `break` in C-like lang.) } -## The "pointy block" syntax isn't specific to for. -## It's just a way to express a block in Perl6. +## The "pointy block" syntax isn't specific to the `for` loop. It's just a way +## to express a block in Perl 6. +sub long-computation { "Finding factors of large primes" } if long-computation() -> $result { - say "The result is $result"; + say "The result is $result."; } ``` ## Operators ```perl6 -## Since Perl languages are very much operator-based languages, -## Perl 6 operators are actually just funny-looking subroutines, in syntactic +## Since Perl languages are very much operator-based languages, Perl 6 +## operators are actually just funny-looking subroutines, in syntactic ## categories, like infix:<+> (addition) or prefix:<!> (bool not). ## The categories are: @@ -394,105 +429,127 @@ if long-computation() -> $result { ## - "postfix": after (like `++` in `$a++`). ## - "infix": in between (like `*` in `4 * 3`). ## - "circumfix": around (like `[`-`]` in `[1, 2]`). -## - "post-circumfix": around, after another term (like `{`-`}` in -## `%hash{'key'}`) +## - "post-circumfix": around, after another term (like `{`-`}` in +## `%hash{'key'}`) ## The associativity and precedence list are explained below. -## Alright, you're set to go ! +## Alright, you're set to go! -## * Equality Checking +## Equality Checking +##------------------ ## - `==` is numeric comparison -3 == 4; # False -3 != 4; # True +3 == 4; #=> False +3 != 4; #=> True ## - `eq` is string comparison -'a' eq 'b'; -'a' ne 'b'; # not equal -'a' !eq 'b'; # same as above +'a' eq 'b'; #=> False +'a' ne 'b'; #=> True, not equal +'a' !eq 'b'; #=> True, same as above ## - `eqv` is canonical equivalence (or "deep equality") -(1, 2) eqv (1, 3); +(1, 2) eqv (1, 3); #=> False +(1, 2) eqv (1, 2); #=> True +Int === Int #=> True -## - Smart Match Operator: `~~` +## - `~~` is the smart match operator ## Aliases the left hand side to $_ and then evaluates the right hand side. ## Here are some common comparison semantics: -## String or Numeric Equality - +## String or numeric equality 'Foo' ~~ 'Foo'; # True if strings are equal. -12.5 ~~ 12.50; # True if numbers are equal. +12.5 ~~ 12.50; # True if numbers are equal. ## Regex - For matching a regular expression against the left side. -## Returns a (Match) object, which evaluates as True if regexp matches. +## Returns a `Match` object, which evaluates as True if regexp matches. my $obj = 'abc' ~~ /a/; -say $obj; # 「a」 -say $obj.WHAT; # (Match) +say $obj; #=> 「a」 +say $obj.WHAT; #=> (Match) ## Hashes -'key' ~~ %hash; # True if key exists in hash - -## Type - Checks if left side "has type" (can check superclasses and roles) - -1 ~~ Int; # True +'key' ~~ %hash; # True if key exists in hash. -## Smart-matching against a boolean always returns that boolean (and will warn). +## Type - Checks if left side "is of type" (can check superclasses and +## roles). +say 1 ~~ Int; #=> True -1 ~~ True; # True -False ~~ True; # True +## Smart-matching against a boolean always returns that boolean +## (and will warn). +say 1 ~~ True; #=> True +say False ~~ True; #=> True -## General syntax is $arg ~~ &bool-returning-function; -## For a complete list of combinations, use this table: +## General syntax is `$arg ~~ &bool-returning-function;`. For a complete list +## of combinations, use this table: ## http://perlcabal.org/syn/S03.html#Smart_matching -## You also, of course, have `<`, `<=`, `>`, `>=`. -## Their string equivalent are also available : `lt`, `le`, `gt`, `ge`. -3 > 4; +## Of course, you also use `<`, `<=`, `>`, `>=` for numeric comparison. +## Their string equivalent are also available: `lt`, `le`, `gt`, `ge`. +3 > 4; # False +3 >= 4; # False +3 < 4; # True +3 <= 4; # True +'a' gt 'b'; # False +'a' ge 'b'; # False +'a' lt 'b'; # True +'a' le 'b'; # True + + +## Range constructor +##------------------ +3 .. 7; # 3 to 7, both included +3 ..^ 7; # 3 to 7, exclude right endpoint. +3 ^.. 7; # 3 to 7, exclude left endpoint. Same as `4..7`. +3 ^..^ 7; # 3 to 7, exclude both endpoints. Same as `4..6`. -## * Range constructors -3 .. 7; # 3 to 7, both included -## `^` on either side them exclusive on that side : -3 ^..^ 7; # 3 to 7, not included (basically `4 .. 6`) ## This also works as a shortcut for `0..^N`: -^10; # means 0..^10 +^10; # means 0..^10 ## This also allows us to demonstrate that Perl 6 has lazy/infinite arrays, ## using the Whatever Star: -my @array = 1..*; # 1 to Infinite ! `1..Inf` is the same. -say @array[^10]; # you can pass arrays as subscripts and it'll return - # an array of results. This will print - # "1 2 3 4 5 6 7 8 9 10" (and not run out of memory !) -## Note : when reading an infinite list, Perl 6 will "reify" the elements +my @array = 1..*; # 1 to Infinite! Equivalent to `1..Inf`. +say @array[^10]; # You can pass ranges as subscripts and it'll return + # an array of results. This will print + # "1 2 3 4 5 6 7 8 9 10" (and not run out of memory!) + +## Note: when reading an infinite list, Perl 6 will "reify" the elements ## it needs, then keep them in memory. They won't be calculated more than once. ## It also will never calculate more elements that are needed. -## Trying -## An array subscript can also be a closure. -## It'll be called with the length as the argument +## An array subscript can also be a closure. It'll be called with the length +## as the argument: say join(' ', @array[15..*]); #=> 15 16 17 18 19 ## which is equivalent to: say join(' ', @array[-> $n { 15..$n }]); + ## Note: if you try to do either of those with an infinite array, -## you'll trigger an infinite loop (your program won't finish) +## you'll trigger an infinite loop (your program won't finish). -## You can use that in most places you'd expect, even assigning to an array +## You can use that in most places you'd expect, even when assigning to +## an array: my @numbers = ^20; -## Here numbers increase by "6"; more on `...` operator later. -my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; +## Here the numbers increase by 6, like an arithmetic sequence; more on the +## sequence (`...`) operator later. +my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; @numbers[5..*] = 3, 9 ... *; # even though the sequence is infinite, # only the 15 needed values will be calculated. -say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 - # (only 20 values) +say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 + # (only 20 values) -## * And &&, Or || -3 && 4; # 4, which is Truthy. Calls `.Bool` on `4` and gets `True`. -0 || False; # False. Calls `.Bool` on `0` +## and (&&), or (||) +##------------------ +3 && 4; # 4, which is Truthy. Calls `.Bool` on both 3 and 4 and gets `True` + # so it returns 4 since both are `True`. +3 && 0; # 0 +0 && 4; # 0 -## * Short-circuit (and tight) versions of the above -# Returns the first argument that evaluates to False, or the last argument. +0 || False; # False. Calls `.Bool` on `0` and `False` which are both `False` + # so it retusns `False` since both are `False`. + +## Short-circuit (and tight) versions of the above +## Return the first argument that evaluates to False, or the last argument. my ( $a, $b, $c ) = 1, 0, 2; $a && $b && $c; # Returns 0, the first False value @@ -500,203 +557,242 @@ $a && $b && $c; # Returns 0, the first False value ## || Returns the first argument that evaluates to True $b || $a; # 1 -## And because you're going to want them, -## you also have compound assignment operators: -$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2; -$b %%= 5; # divisible by and assignment +## And because you're going to want them, you also have compound assignment +## operators: +$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2; +$b %%= 5; # divisible by and assignment. Equivalent to $b = $b %% 2; +$c div= 3; # return divisor and assignment. Equivalent to $c = $c div 3; +$d mod= 4; # return remainder and assignment. Equivalent to $d = $d mod 4; @array .= sort; # calls the `sort` method and assigns the result back ``` -## More on subs ! +## More on subs! ```perl6 -## As we said before, Perl 6 has *really* powerful subs. We're going to see -## a few more key concepts that make them better than in any other language :-). +## As we said before, Perl 6 has *really* powerful subs. We're going +## to see a few more key concepts that make them better than in any +## other language :-). ``` -### Unpacking ! +### Unpacking! ```perl6 -## It's the ability to "extract" arrays and keys (AKA "destructuring"). -## It'll work in `my`s and in parameter lists. +## Unpacking is the ability to "extract" arrays and keys +## (AKA "destructuring"). It'll work in `my`s and in parameter lists. my ($f, $g) = 1, 2; -say $f; #=> 1 -my ($, $, $h) = 1, 2, 3; # keep the non-interesting anonymous -say $h; #=> 3 +say $f; #=> 1 +my ($, $, $h) = 1, 2, 3; # keep the non-interesting values anonymous (`$`) +say $h; #=> 3 my ($head, *@tail) = 1, 2, 3; # Yes, it's the same as with "slurpy subs" my (*@small) = 1; -sub unpack_array(@array [$fst, $snd]) { - say "My first is $fst, my second is $snd ! All in all, I'm @array[]."; +sub unpack_array( @array [$fst, $snd] ) { + say "My first is $fst, my second is $snd! All in all, I'm @array[]."; # (^ remember the `[]` to interpolate the array) } -unpack_array(@tail); #=> My first is 2, my second is 3 ! All in all, I'm 2 3 +unpack_array(@tail); #=> My first is 2, my second is 3! All in all, I'm 2 3. ## If you're not using the array itself, you can also keep it anonymous, ## much like a scalar: -sub first-of-array(@ [$fst]) { $fst } +sub first-of-array( @ [$fst] ) { $fst } first-of-array(@small); #=> 1 -first-of-array(@tail); # Throws an error "Too many positional parameters passed" - # (which means the array is too big). +first-of-array(@tail); # Error: "Too many positional parameters passed" + # (which means the array is too big). -## You can also use a slurp ... +## You can also use a slurp... sub slurp-in-array(@ [$fst, *@rest]) { # You could keep `*@rest` anonymous - say $fst + @rest.elems; # `.elems` returns a list's length. - # Here, `@rest` is `(3,)`, since `$fst` holds the `2`. + say $fst + @rest.elems; # `.elems` returns a list's length. + # Here, `@rest` is `(3,)`, since `$fst` + # holds the `2`. } -slurp-in-array(@tail); #=> 3 +slurp-in-array(@tail); #=> 3 ## You could even extract on a slurpy (but it's pretty useless ;-).) -sub fst(*@ [$fst]) { # or simply : `sub fst($fst) { ... }` - say $fst; +sub fst(*@ [$fst]) { # or simply: `sub fst($fst) { ... }` + say $fst; } -fst(1); #=> 1 +fst(1); #=> 1 fst(1, 2); # errors with "Too many positional parameters passed" -## You can also destructure hashes (and classes, which you'll learn about later) -## The syntax is basically `%hash-name (:key($variable-to-store-value-in))`. +## You can also destructure hashes (and classes, which you'll learn about +## later). The syntax is basically the same as +## `%hash-name (:key($variable-to-store-value-in))`. ## The hash can stay anonymous if you only need the values you extracted. -sub key-of(% (:value($val), :qua($qua))) { - say "Got val $val, $qua times."; +sub key-of( % (:value($val), :qua($qua)) ) { + say "Got val $val, $qua times."; } -## Then call it with a hash: (you need to keep the brackets for it to be a hash) -key-of({value => 'foo', qua => 1}); +## Then call it with a hash. You need to keep the curly braces for it to be a +## hash or use `%()` instead to indicate a hash is being passed. +key-of({value => 'foo', qua => 1}); #=> Got val foo, 1 times. +key-of(%(value => 'foo', qua => 1)); #=> Got val foo, 1 times. #key-of(%hash); # the same (for an equivalent `%hash`) -## The last expression of a sub is returned automatically -## (though you may use the `return` keyword, of course): -sub next-index($n) { - $n + 1; +## The last expression of a sub is returned automatically (though you may +## indicate explicitly by using the `return` keyword, of course): +sub next-index( $n ) { + $n + 1; } my $new-n = next-index(3); # $new-n is now 4 -## This is true for everything, except for the looping constructs -## (due to performance reasons): there's reason to build a list -## if we're just going to discard all the results. -## If you still want to build one, you can use the `do` statement prefix: -## (or the `gather` prefix, which we'll see later) -sub list-of($n) { - do for ^$n { # note the use of the range-to prefix operator `^` (`0..^N`) - $_ # current loop iteration - } +## This is true for everything, except for the looping constructs (due to +## performance reasons): there's no reason to build a list if we're just going to +## discard all the results. If you still want to build one, you can use the +## `do` statement prefix or the `gather` prefix, which we'll see later: + +sub list-of( $n ) { + do for ^$n { # note the range-to prefix operator `^` (`0..^N`) + $_ # current loop iteration known as the "topic" variable + } } my @list3 = list-of(3); #=> (0, 1, 2) ``` -### lambdas +### lambdas (or anonymous subroutines) ```perl6 -## You can create a lambda with `-> {}` ("pointy block") or `{}` ("block") -my &lambda = -> $argument { "The argument passed to this lambda is $argument" } +## You can create a lambda with `-> {}` ("pointy block") , +## `{}` ("block") or `sub {}`. + +my &lambda1 = -> $argument { + "The argument passed to this lambda is $argument" +} + +my &lambda2 = { + "The argument passed to this lambda is $_" +} + +my &lambda3 = sub ($argument) { + "The argument passed to this lambda is $argument" +} + ## `-> {}` and `{}` are pretty much the same thing, except that the former can ## take arguments, and that the latter can be mistaken as a hash by the parser. -## We can, for example, add 3 to each value of an array using map: +## We can, for example, add 3 to each value of an array using the +## `map` function with a lambda: my @arrayplus3 = map({ $_ + 3 }, @array); # $_ is the implicit argument ## A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`): ## A block doesn't have a "function context" (though it can have arguments), -## which means that if you return from it, -## you're going to return from the parent function. Compare: -sub is-in(@array, $elem) { - # this will `return` out of the `is-in` sub - # once the condition evaluated to True, the loop won't be run anymore - map({ return True if $_ == $elem }, @array); -} -sub truthy-array(@array) { - # this will produce an array of `True` and `False`: - # (you can also say `anon sub` for "anonymous subroutine") - map(sub ($i) { if $i { return True } else { return False } }, @array); - # ^ the `return` only returns from the anonymous `sub` -} - -## You can also use the "whatever star" to create an anonymous function +## which means that if you return from it, you're going to return from the +## parent function. Compare: +sub is-in( @array, $elem ) { + # this will `return` out of the `is-in` sub once the condition evaluated + ## to True, the loop won't be run anymore. + map({ return True if $_ == $elem }, @array); +} +## with: +sub truthy-array( @array ) { + # this will produce an array of `True` and `False`: + # (you can also say `anon sub` for "anonymous subroutine") + map(sub ($i) { if $i { return True } else { return False } }, @array); + # ^ the `return` only returns from the anonymous `sub` +} + +## The `anon` declarator can be used to create an anonymous sub from a +## regular subroutine. The regular sub knows its name but its symbol is +## prevented from getting installed in the lexical scope, the method table +## and everywhere else. + +my $anon-sum = anon sub summation(*@a) { [+] *@a } +say $anon-sum.name; #=> summation +say $anon-sum(2, 3, 5); #=> 10 +#say summation; #=> Error: Undeclared routine: ... + +## You can also use the "whatever star" to create an anonymous subroutine. ## (it'll stop at the furthest operator in the current expression) -my @arrayplus3 = map(*+3, @array); # `*+3` is the same as `{ $_ + 3 }` +my @arrayplus3 = map(*+3, @array); # `*+3` is the same as `{ $_ + 3 }` my @arrayplus3 = map(*+*+3, @array); # Same as `-> $a, $b { $a + $b + 3 }` # also `sub ($a, $b) { $a + $b + 3 }` -say (*/2)(4); #=> 2 - # Immediately execute the function Whatever created. +say (*/2)(4); #=> 2 + # Immediately execute the function Whatever created. say ((*+3)/5)(5); #=> 1.6 - # works even in parens ! - -## But if you need to have more than one argument (`$_`) -## in a block (without wanting to resort to `-> {}`), -## you can also use the implicit argument syntax, `$^` : -map({ $^a + $^b + 3 }, @array); # equivalent to following: -map(sub ($a, $b) { $a + $b + 3 }, @array); # (here with `sub`) - -## Note : those are sorted lexicographically. -# `{ $^b / $^a }` is like `-> $a, $b { $b / $a }` + # It works even in parens! + +## But if you need to have more than one argument (`$_`) in a block (without +## wanting to resort to `-> {}`), you can also use the implicit argument +## syntax, `$^`: +map({ $^a + $^b + 3 }, @array); +# which is equivalent to the following which uses a `sub`: +map(sub ($a, $b) { $a + $b + 3 }, @array); + +## The parameters `$^a`, `$^b`, etc. are known as placeholder parameters or +## self-declared positional parameters. They're sorted lexicographically so +## `{ $^b / $^a }` is equivalent `-> $a, $b { $b / $a }`. ``` ### About types... ```perl6 -## Perl6 is gradually typed. This means you can specify the type -## of your variables/arguments/return types, or you can omit them -## and they'll default to "Any". -## You obviously get access to a few base types, like Int and Str. -## The constructs for declaring types are "class", "role", -## which you'll see later. - -## For now, let us examine "subset": -## a "subset" is a "sub-type" with additional checks. -## For example: "a very big integer is an Int that's greater than 500" -## You can specify the type you're subtyping (by default, Any), -## and add additional checks with the "where" keyword: +## Perl 6 is gradually typed. This means you can specify the type of your +## variables/arguments/return types, or you can omit the type annotations in +## in which case they'll default to `Any`. Obviously you get access to a few +## base types, like `Int` and `Str`. The constructs for declaring types are +## "subset", "class", "role", etc. which you'll see later. + +## For now, let us examine "subset" which is a "sub-type" with additional +## checks. For example, "a very big integer is an Int that's greater than 500". +## You can specify the type you're subtyping (by default, `Any`), and add +## additional checks with the `where` clause: subset VeryBigInteger of Int where * > 500; +## Or the set of the whole numbers: +subset WholeNumber of Int where * >= 0; ``` ### Multiple Dispatch ```perl6 ## Perl 6 can decide which variant of a `sub` to call based on the type of the -## arguments, or on arbitrary preconditions, like with a type or a `where`: +## arguments, or on arbitrary preconditions, like with a type or `where`: -## with types -multi sub sayit(Int $n) { # note the `multi` keyword here +## with types: +multi sub sayit( Int $n ) { # note the `multi` keyword here say "Number: $n"; } -multi sayit(Str $s) { # a multi is a `sub` by default +multi sayit( Str $s ) { # a multi is a `sub` by default say "String: $s"; } -sayit("foo"); # prints "String: foo" -sayit(True); # fails at *compile time* with - # "calling 'sayit' will never work with arguments of types ..." +sayit("foo"); #=> "String: foo" +sayit(25); #=> "Number: 25" +sayit(True); # fails at *compile time* with "calling 'sayit' will never + # work with arguments of types ..." -## with arbitrary precondition (remember subsets?): -multi is-big(Int $n where * > 50) { "Yes !" } # using a closure -multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching - # (could use a regexp, etc) +## with arbitrary preconditions (remember subsets?): +multi is-big(Int $n where * > 50) { "Yes!" } # using a closure +multi is-big(Int $n where {$_ > 50}) { "Yes!" } # similar to above +multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching + # (could use a regexp, etc) multi is-big(Int $) { "No" } subset Even of Int where * %% 2; - multi odd-or-even(Even) { "Even" } # The main case using the type. # We don't name the argument. -multi odd-or-even($) { "Odd" } # "else" +multi odd-or-even($) { "Odd" } # "everthing else" hence the $ variable -## You can even dispatch based on a positional's argument presence ! -multi with-or-without-you(:$with!) { # You need make it mandatory to - # be able to dispatch against it. - say "I can live ! Actually, I can't."; +## You can even dispatch based on the presence of positional and +## named arguments: +multi with-or-without-you($with) { + say "I wish I could but I can't"; +} +multi with-or-without-you(:$with) { + say "I can live! Actually, I can't."; } multi with-or-without-you { - say "Definitely can't live."; + say "Definitely can't live."; } -## This is very, very useful for many purposes, like `MAIN` subs (covered -## later), and even the language itself is using it in several places. + +## This is very, very useful for many purposes, like `MAIN` subs (covered +## later), and even the language itself uses it in several places. ## ## - `is`, for example, is actually a `multi sub` named `trait_mod:<is>`, ## and it works off that. ## - `is rw`, is simply a dispatch to a function with this signature: ## sub trait_mod:<is>(Routine $r, :$rw!) {} ## -## (commented because running this would be a terrible idea !) +## (commented out because running this would be a terrible idea!) ``` ## Scoping @@ -705,175 +801,207 @@ multi with-or-without-you { ## In Perl 6, unlike many scripting languages, (such as Python, Ruby, PHP), ## you must declare your variables before using them. The `my` declarator ## you have learned uses "lexical scoping". There are a few other declarators, -## (`our`, `state`, ..., ) which we'll see later. -## This is called "lexical scoping", where in inner blocks, -## you can access variables from outer blocks. +## (`our`, `state`, ..., ) which we'll see later. This is called +## "lexical scoping", where in inner blocks, you can access variables from +## outer blocks. my $file_scoped = 'Foo'; sub outer { - my $outer_scoped = 'Bar'; - sub inner { - say "$file_scoped $outer_scoped"; - } - &inner; # return the function + my $outer_scoped = 'Bar'; + sub inner { + say "$file_scoped $outer_scoped"; + } + &inner; # return the function } -outer()(); #=> 'Foo Bar' +outer()(); #=> 'Foo Bar' ## As you can see, `$file_scoped` and `$outer_scoped` were captured. -## But if we were to try and use `$bar` outside of `foo`, +## But if we were to try and use `$outer_scoped` outside the `outer` sub, ## the variable would be undefined (and you'd get a compile time error). ``` ## Twigils ```perl6 -## There are many special `twigils` (composed sigil's) in Perl 6. -## Twigils define the variables' scope. +## There are many special `twigils` (composed sigils) in Perl 6. Twigils +## define the variables' scope. ## The * and ? twigils work on standard variables: ## * Dynamic variable ## ? Compile-time variable ## The ! and the . twigils are used with Perl 6's objects: -## ! Attribute (class member) +## ! Attribute (instance attribute) ## . Method (not really a variable) -## `*` Twigil: Dynamic Scope -## These variables use the`*` twigil to mark dynamically-scoped variables. +## `*` twigil: Dynamic Scope +## These variables use the `*` twigil to mark dynamically-scoped variables. ## Dynamically-scoped variables are looked up through the caller, not through -## the outer scope +## the outer scope. my $*dyn_scoped_1 = 1; my $*dyn_scoped_2 = 10; sub say_dyn { - say "$*dyn_scoped_1 $*dyn_scoped_2"; + say "$*dyn_scoped_1 $*dyn_scoped_2"; } sub call_say_dyn { my $*dyn_scoped_1 = 25; # Defines $*dyn_scoped_1 only for this sub. - $*dyn_scoped_2 = 100; # Will change the value of the file scoped variable. - say_dyn(); #=> 25 100 $*dyn_scoped 1 and 2 will be looked for in the call. - # It uses the value of $*dyn_scoped_1 from inside this sub's - # lexical scope even though the blocks aren't nested (they're - # call-nested). -} -say_dyn(); #=> 1 10 + $*dyn_scoped_2 = 100; # Will change the value of the file scoped variable. + say_dyn(); #=> 25 100, $*dyn_scoped 1 and 2 will be looked + # for in the call. + # It uses the value of $*dyn_scoped_1 from inside + # this sub's lexical scope even though the blocks + # aren't nested (they're call-nested). +} +say_dyn(); #=> 1 10 call_say_dyn(); #=> 25 100 # Uses $*dyn_scoped_1 as defined in call_say_dyn even though # we are calling it from outside. -say_dyn(); #=> 1 100 We changed the value of $*dyn_scoped_2 in call_say_dyn - # so now its value has changed. +say_dyn(); #=> 1 100 We changed the value of $*dyn_scoped_2 in + # call_say_dyn so now its value has changed. ``` ## Object Model ```perl6 ## To call a method on an object, add a dot followed by the method name: -## => $object.method +## `$object.method` + ## Classes are declared with the `class` keyword. Attributes are declared -## with the `has` keyword, and methods declared with `method`. -## Every attribute that is private uses the ! twigil for example: `$!attr`. -## Immutable public attributes use the `.` twigil. -## (you can make them mutable with `is rw`) -## The easiest way to remember the `$.` twigil is comparing it to how methods -## are called. - -## Perl 6's object model ("SixModel") is very flexible, -## and allows you to dynamically add methods, change semantics, etc ... -## (these will not all be covered here, and you should refer to: +## with the `has` keyword, and methods declared with the `method` keyword. + +## Every attribute that is private uses the ! twigil. For example: `$!attr`. +## Immutable public attributes use the `.` twigil which creates a read-only +## method named after the attribute. In fact, declaring an attribute with `.` +## is equivalent to declaring the same attribute with `!` and then creating +## a read-only method with the attribute's name. However, this is done for us +## by Perl 6 automatically. The easiest way to remember the `$.` twigil is +## by comparing it to how methods are called. + +## Perl 6's object model ("SixModel") is very flexible, and allows you to +## dynamically add methods, change semantics, etc... Unfortunately, these will +## not all be covered here, and you should refer to: ## https://docs.perl6.org/language/objects.html. -class Attrib-Class { - has $.attrib; # `$.attrib` is immutable. - # From inside the class, use `$!attrib` to modify it. - has $.other-attrib is rw; # You can mark a public attribute `rw`. - has Int $!private-attrib = 10; - - method get-value { - $.attrib + $!private-attrib; - } +class Human { + has Str $.name; # `$.name` is immutable but with an accessor method. + has Str $.bcountry; # Use `$!bplace` to modify it inside the class. + has Str $.ccountry is rw; # This attribute can be modified from outside. + has Int $!age = 0; # A private attribute with default value. - method set-value($param) { # Methods can take parameters - $!attrib = $param; # This works, because `$!` is always mutable. - # $.attrib = $param; # Wrong: You can't use the `$.` immutable version. + method birthday { + $!age += 1; # Add a year to human's age + } - $.other-attrib = 5; # This works, because `$.other-attrib` is `rw`. - } + method get-age { + return $!age; + } - method !private-method { - say "This method is private to the class !"; - } + # This method is private to the class. Note the `!` before the + # method's name. + method !do-decoration { + return "$!name was born in $!bcountry and now lives in $!ccountry." + } + + # This method is public, just like `birthday` and `get-age`. + method get-info { + self.do-decoration; # Invoking a method on `self` inside the class. + # Use `self!priv-method` for private method. + # Use `self.publ-method` for public method. + } }; -## Create a new instance of Attrib-Class with $.attrib set to 5 : +## Create a new instance of Human class with $.attrib set to 5. ## Note: you can't set private-attribute from here (more later on). -my $class-obj = Attrib-Class.new(attrib => 5); -say $class-obj.get-value; #=> 15 -# $class-obj.attrib = 5; # This fails, because the `has $.attrib` is immutable -$class-obj.other-attrib = 10; # This, however, works, because the public - # attribute is mutable (`rw`). +my $person1 = Human.new( + name => "Jord", + bcountry = "Iceland", + ccountry => "Iceland" +); + +say $person1.name; #=> Jord +say $person1.bcountry; #=> Togo +say $person1.ccountry; #=> Togo + + +# $person1.bcountry = "Mali"; # This fails, because the `has $.bcountry` + # is immutable. Jord can't change his birthplace. +$person1.ccountry = "France"; # This works because the `$.ccountry` is mutable + # (`is rw`). Now Jord's current country is France. + +# Calling methods on the instance objects. +$person1.birthday; #=> 1 +$person1.get-info; #=> Jord was born in Togo and now lives in France. +$person1.do-decoration; # This fails since the method `do-decoration` is + # private. ``` ### Object Inheritance ```perl6 -## Perl 6 also has inheritance (along with multiple inheritance) -## While `method`'s are inherited, `submethod`'s are not. -## Submethods are useful for object construction and destruction tasks, -## such as BUILD, or methods that must be overridden by subtypes. -## We will learn about BUILD later on. +## Perl 6 also has inheritance (along with multiple inheritance). While +## methods are inherited, submethods are not. Submethods are useful for +## object construction and destruction tasks, such as BUILD, or methods that +## must be overridden by subtypes. We will learn about BUILD later on. class Parent { - has $.age; - has $.name; - # This submethod won't be inherited by Child. - submethod favorite-color { - say "My favorite color is Blue"; - } - # This method is inherited - method talk { say "Hi, my name is $!name" } + has $.age; + has $.name; + + # This submethod won't be inherited by the Child class. + submethod favorite-color { + say "My favorite color is Blue"; + } + + # This method is inherited + method talk { say "Hi, my name is $!name" } } + # Inheritance uses the `is` keyword class Child is Parent { - method talk { say "Goo goo ga ga" } - # This shadows Parent's `talk` method, This child hasn't learned to speak yet! + method talk { say "Goo goo ga ga" } + # This shadows Parent's `talk` method. + # This child hasn't learned to speak yet! } + my Parent $Richard .= new(age => 40, name => 'Richard'); -$Richard.favorite-color; #=> "My favorite color is Blue" -$Richard.talk; #=> "Hi, my name is Richard" -## $Richard is able to access the submethod, he knows how to say his name. +$Richard.favorite-color; #=> "My favorite color is Blue" +$Richard.talk; #=> "Hi, my name is Richard" +## $Richard is able to access the submethod and he knows how to say his name. my Child $Madison .= new(age => 1, name => 'Madison'); -$Madison.talk; # prints "Goo goo ga ga" due to the overridden method. -# $Madison.favorite-color # does not work since it is not inherited +$Madison.talk; #=> "Goo goo ga ga", due to the overridden method. +# $Madison.favorite-color # does not work since it is not inherited. ## When you use `my T $var`, `$var` starts off with `T` itself in it, ## so you can call `new` on it. ## (`.=` is just the dot-call and the assignment operator: -## `$a .= b` is the same as `$a = $a.b`) +## `$a .= b` is the same as `$a = $a.b`) ## Also note that `BUILD` (the method called inside `new`) -## will set parent properties too, so you can pass `val => 5`. +## will set parent's properties too, so you can pass `val => 5`. ``` ### Roles, or Mixins ```perl6 -## Roles are supported too (also called Mixins in other languages) +## Roles are supported too (which are called Mixins in other languages) role PrintableVal { - has $!counter = 0; - method print { - say $.val; - } + has $!counter = 0; + method print { + say $.val; + } } -## you "import" a mixin (a "role") with "does": +## you "apply" a role (or mixin) with `does` keyword: class Item does PrintableVal { - has $.val; + has $.val; - ## When `does`-ed, a `role` literally "mixes in" the class: - ## the methods and attributes are put together, which means a class can access - ## the private attributes/methods of its roles (but not the inverse !): - method access { - say $!counter++; - } + ## When `does`-ed, a `role` literally "mixes in" the class: + ## the methods and attributes are put together, which means a class + ## can access the private attributes/methods of its roles (but + ## not the inverse!): + method access { + say $!counter++; + } ## However, this: ## method print {} @@ -881,9 +1009,9 @@ class Item does PrintableVal { ## (this means a parent class can shadow a child class's `multi print() {}`, ## but it's an error if a role does) - ## NOTE: You can use a role as a class (with `is ROLE`). In this case, - ## methods will be shadowed, since the compiler will consider `ROLE` to - ## be a class. + ## NOTE: You can use a role as a class (with `is ROLE`). In this case, + ## methods will be shadowed, since the compiler will consider `ROLE` + ## to be a class. } ``` @@ -891,91 +1019,109 @@ class Item does PrintableVal { ```perl6 ## Exceptions are built on top of classes, in the package `X` (like `X::IO`). -## In Perl6 exceptions are automatically 'thrown' -open 'foo'; #> Failed to open file foo: no such file or directory -## It will also print out what line the error was thrown at and other error info +## In Perl6 exceptions are automatically 'thrown': +open 'foo'; #=> Failed to open file foo: no such file or directory +## It will also print out what line the error was thrown at +## and other error info. ## You can throw an exception using `die`: die 'Error!'; #=> Error! ## Or more explicitly: -die X::AdHoc.new(payload => 'Error!'); +X::AdHoc.new(payload => 'Error!').throw; #=> Error! ## In Perl 6, `orelse` is similar to the `or` operator, except it only matches -## undefined variables instead of anything evaluating as false. +## undefined variables instead of anything evaluating as `False`. ## Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str` ## and other types that have not been initialized to any value yet. ## You can check if something is defined or not using the defined method: my $uninitialized; -say $uninitiazilzed.defined; #> False -## When using `orelse` it will disarm the exception and alias $_ to that failure -## This will avoid it being automatically handled and printing lots of scary -## error messages to the screen. -## We can use the exception method on $_ to access the exception +say $uninitiazilzed.defined; #=> False + +## When using `orelse` it will disarm the exception and alias $_ to that +## failure. This will prevent it to being automatically handled and printing +## lots of scary error messages to the screen. We can use the `exception` +## method on the `$_` variable to access the exception open 'foo' orelse say "Something happened {.exception}"; ## This also works: -open 'foo' orelse say "Something happened $_"; #> Something happened - #> Failed to open file foo: no such file or directory -## Both of those above work but in case we get an object from the left side that -## is not a failure we will probably get a warning. We see below how we can use -## `try` and `CATCH` to be more specific with the exceptions we catch. +open 'foo' orelse say "Something happened $_"; #=> Something happened + #=> Failed to open file foo: no such file or directory +## Both of those above work but in case we get an object from the left side +## that is not a failure we will probably get a warning. We see below how we +## can use try` and `CATCH` to be more specific with the exceptions we catch. ``` ### Using `try` and `CATCH` ```perl6 ## By using `try` and `CATCH` you can contain and handle exceptions without -## disrupting the rest of the program. `try` will set the last exception to -## the special variable `$!` Note: This has no relation to $!variables. +## disrupting the rest of the program. The `try` block will set the last +## exception to the special variable `$!` (known as the error variable). +## Note: This has no relation to $!variables seen inside class definitions. + try open 'foo'; -say "Well, I tried! $!" if defined $!; #> Well, I tried! Failed to open file - #foo: no such file or directory +say "Well, I tried! $!" if defined $!; +#=> Well, I tried! Failed to open file foo: no such file or directory + ## Now, what if we want more control over handling the exception? ## Unlike many other languages, in Perl 6, you put the `CATCH` block *within* -## the block to `try`. Similar to how $_ was set when we 'disarmed' the -## exception with orelse, we also use $_ in the CATCH block. -## Note: ($! is only set *after* the `try` block) -## By default, a `try` has a `CATCH` block that catches -## any exception (`CATCH { default {} }`). +## the block to `try`. Similar to how the `$_` variable was set when we +## 'disarmed' the exception with `orelse`, we also use `$_` in the CATCH block. +## Note: The `$!` variable is only set *after* the `try` block has caught an +## exception. By default, a `try` block has a `CATCH` block of its own that +## catches any exception (`CATCH { default {} }`). -try { my $a = (0 %% 0); CATCH { say "Something happened: $_" } } - #=> Something happened: Attempt to divide by zero using infix:<%%> +try { + my $a = (0 %% 0); + CATCH { + say "Something happened: $_" + } +} +#=> Something happened: Attempt to divide by zero using infix:<%%> + +## You can redefine it using `when`s (and `default`) to handle the exceptions +## you want to catch explicitly: -## You can redefine it using `when`s (and `default`) -## to handle the exceptions you want: try { open 'foo'; - CATCH { # In the `CATCH` block, the exception is set to $_ - when X::AdHoc { say "Error: $_" } - #=>Error: Failed to open file /dir/foo: no such file or directory - - ## Any other exception will be re-raised, since we don't have a `default` - ## Basically, if a `when` matches (or there's a `default`) marks the - ## exception as - ## "handled" so that it doesn't get re-thrown from the `CATCH`. - ## You still can re-throw the exception (see below) by hand. + CATCH { + # In the `CATCH` block, the exception is set to the $_ variable. + when X::AdHoc { + say "Error: $_" + } + when X::Numeric::DivideByZero { + say "Error: $_"; + } + ## Any other exceptions will be re-raised, since we don't have a `default`. + ## Basically, if a `when` matches (or there's a `default`), the + ## exception is marked as "handled" so as to prevent its re-throw + ## from the `CATCH` block. You still can re-throw the exception (see below) + ## by hand. } } +#=>Error: Failed to open file /dir/foo: no such file or directory ## There are also some subtleties to exceptions. Some Perl 6 subs return a -## `Failure`, which is a kind of "unthrown exception". They're not thrown until -## you tried to look at their content, unless you call `.Bool`/`.defined` on -## them - then they're handled. +## `Failure`, which is a wrapper around an `Exception` object which is +## "unthrown". They're not thrown until you try to use the variables containing +## them unless you call `.Bool`/`.defined` on them - then they're handled. ## (the `.handled` method is `rw`, so you can mark it as `False` back yourself) -## ## You can throw a `Failure` using `fail`. Note that if the pragma `use fatal` ## is on, `fail` will throw an exception (like `die`). + fail "foo"; # We're not trying to access the value, so no problem. try { - fail "foo"; - CATCH { - default { say "It threw because we tried to get the fail's value!" } + fail "foo"; + CATCH { + default { + say "It threw because we tried to get the fail's value!" + } } } ## There is also another kind of exception: Control exceptions. -## Those are "good" exceptions, which happen when you change your program's +## Those are "good" exceptions, which happen when you change your program's ## flow, using operators like `return`, `next` or `last`. ## You can "catch" those with `CONTROL` (not 100% working in Rakudo yet). ``` @@ -989,29 +1135,35 @@ try { ## Packages are important - especially as Perl is well-known for CPAN, ## the Comprehensive Perl Archive Network. -## You can use a module (bring its declarations into scope) with `use` +## You can use a module (bring its declarations into scope) with +## the `use` keyword: use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module say from-json('[1]').perl; #=> [1] ## You should not declare packages using the `package` keyword (unlike Perl 5). ## Instead, use `class Package::Name::Here;` to declare a class, or if you only -## want to export variables/subs, you can use `module`. +## want to export variables/subs, you can use `module` instead. + +module Hello::World { # bracketed form + # If `Hello` doesn't exist yet, it'll just be a "stub", + # that can be redeclared as something else later. -module Hello::World { # Bracketed form - # If `Hello` doesn't exist yet, it'll just be a "stub", - # that can be redeclared as something else later. - # ... declarations here ... + # ... declarations here ... } -unit module Parse::Text; # file-scoped form -grammar Parse::Text::Grammar { # A grammar is a package, which you could `use` -} # You will learn more about grammars in the regex section +unit module Parse::Text; # file-scoped form which extends until + # the end of the file + +grammar Parse::Text::Grammar { + # A grammar is a package, which you could `use`. + # You will learn more about grammars in the regex section +} ## As said before, any part of the six model is also a package. ## Since `JSON::Tiny` uses its own `JSON::Tiny::Actions` class, you can use it: my $actions = JSON::Tiny::Actions.new; -## We'll see how to export variables and subs in the next part: +## We'll see how to export variables and subs in the next part. ``` ## Declarators @@ -1020,36 +1172,38 @@ my $actions = JSON::Tiny::Actions.new; ## In Perl 6, you get different behaviors based on how you declare a variable. ## You've already seen `my` and `has`, we'll now explore the others. -## * `our` declarations happen at `INIT` time -- (see "Phasers" below) -## It's like `my`, but it also creates a package variable. -## (All packagish things (`class`, `role`, etc) are `our` by default) -module Var::Increment { - our $our-var = 1; # Note: you can't put a type constraint like Int on an - my $my-var = 22; # `our` variable. - our sub Inc { - - our sub available { # If you try to make inner `sub`s `our`... - # Better know what you're doing (Don't !). - say "Don't do that. Seriously. You'll get burned."; - } +## `our` - these declarations happen at `INIT` time -- (see "Phasers" below). +## It's like `my`, but it also creates a package variable. All packagish +## things such as `class`, `role`, etc. are `our` by default. - my sub unavailable { # `my sub` is the default - say "Can't access me from outside, I'm 'my'!"; - } - say ++$our-var; # Increment the package variable and output its value +module Var::Increment { + our $our-var = 1; # Note: `our`-declared variables cannot be typed. + my $my-var = 22; + + our sub Inc { + our sub available { # If you try to make inner `sub`s `our`... + # ... Better know what you're doing (Don't !). + say "Don't do that. Seriously. You'll get burned."; + } + + my sub unavailable { # `sub`s are `my`-declared by default + say "Can't access me from outside, I'm 'my'!"; + } + say ++$our-var; # Increment the package variable and output its value } } -say $Var::Increment::our-var; #=> 1 This works -say $Var::Increment::my-var; #=> (Any) This will not work. -Var::Increment::Inc; #=> 2 -Var::Increment::Inc; #=> 3 # Notice how the value of $our-var was - # retained. -Var::Increment::unavailable; #> Could not find symbol '&unavailable' +say $Var::Increment::our-var; #=> 1, this works! +say $Var::Increment::my-var; #=> (Any), this will not work! + +Var::Increment::Inc; #=> 2 +Var::Increment::Inc; #=> 3 , notice how the value of $our-var was + # retained. +Var::Increment::unavailable; #=> Could not find symbol '&unavailable' -## * `constant` (happens at `BEGIN` time) -## You can use the `constant` keyword to declare a compile-time variable/symbol: +## `constant` - these declarations happen at `BEGIN` time. You can use +## the `constant` keyword to declare a compile-time variable/symbol: constant Pi = 3.14; constant $var = 1; @@ -1057,12 +1211,12 @@ constant $var = 1; constant why-not = 5, 15 ... *; say why-not[^5]; #=> 5 15 25 35 45 -## * `state` (happens at run time, but only once) -## State variables are only initialized one time -## (they exist in other languages such as C as `static`) +## `state` - these declarations happen at run time, but only once. State +## variables are only initialized one time. In other languages such as C +## they exist as `static` variables. sub fixed-rand { - state $val = rand; - say $val; + state $val = rand; + say $val; } fixed-rand for ^10; # will print the same number 10 times @@ -1070,40 +1224,42 @@ fixed-rand for ^10; # will print the same number 10 times ## If you declare a function with a `state` within a loop, it'll re-create the ## variable for each iteration of the loop. See: for ^5 -> $a { - sub foo { - state $val = rand; # This will be a different value for every value of `$a` - } - for ^5 -> $b { - say foo; # This will print the same value 5 times, but only 5. - # Next iteration will re-run `rand`. - } + sub foo { + state $val = rand; # This will be a different value for + # every value of `$a` + } + for ^5 -> $b { + say foo; # This will print the same value 5 times, + # but only 5. Next iteration will re-run `rand`. + } } ``` ## Phasers ```perl6 -## Phasers in Perl 6 are blocks that happen at determined points of time in your -## program. They are called phasers because they mark a change in the phase -## of a program. For example, when the program is compiled, a for loop runs, -## you leave a block, or an exception gets thrown. -## (`CATCH` is actually a phaser!) -## Some of them can be used for their return values, some of them can't -## (those that can have a "[*]" in the beginning of their explanation text). -## Let's have a look ! - -## * Compile-time phasers +## Phasers in Perl 6 are blocks that happen at determined points of time in +## your program. They are called phasers because they mark a change in the +## phase of a program. For example, when the program is compiled, a for loop +## runs, you leave a block, or an exception gets thrown (The `CATCH` block is +## actually a phaser!). Some of them can be used for their return values, +## some of them can't (those that can have a "[*]" in the beginning of their +## explanation text). Let's have a look! + +## Compile-time phasers BEGIN { say "[*] Runs at compile time, as soon as possible, only once" } CHECK { say "[*] Runs at compile time, as late as possible, only once" } -## * Run-time phasers +## Run-time phasers INIT { say "[*] Runs at run time, as soon as possible, only once" } -END { say "Runs at run time, as late as possible, only once" } +END { say "Runs at run time, as late as possible, only once" } -## * Block phasers +## Block phasers ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" } -LEAVE { say "Runs everytime you leave a block, even when an exception - happened. Repeats on loop blocks." } +LEAVE { + say "Runs everytime you leave a block, even when an exception + happened. Repeats on loop blocks." +} PRE { say "Asserts a precondition at every block entry, @@ -1112,7 +1268,7 @@ PRE { an exception of type X::Phaser::PrePost is thrown."; } -## example: +## Example: for 0..2 { PRE { $_ > 1 } # This is going to blow up with "Precondition failed" } @@ -1123,83 +1279,86 @@ POST { say "If this block doesn't return a truthy value, an exception of type X::Phaser::PrePost is thrown, like PRE."; } + for 0..2 { POST { $_ < 2 } # This is going to blow up with "Postcondition failed" } -## * Block/exceptions phasers +## Block/exceptions phasers sub { KEEP { say "Runs when you exit a block successfully (without throwing an exception)" } - UNDO { say "Runs when you exit a block unsuccessfully + UNDO { say "Runs when you exit a block unsuccessfully (by throwing an exception)" } } -## * Loop phasers +## Loop phasers for ^5 { FIRST { say "[*] The first time the loop is run, before ENTER" } - NEXT { say "At loop continuation time, before LEAVE" } - LAST { say "At loop termination time, after LEAVE" } + NEXT { say "At loop continuation time, before LEAVE" } + LAST { say "At loop termination time, after LEAVE" } } -## * Role/class phasers +## Role/class phasers COMPOSE { "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" } -## They allow for cute tricks or clever code ...: +## They allow for cute tricks or clever code...: say "This code took " ~ (time - CHECK time) ~ "s to compile"; ## ... or clever organization: sub do-db-stuff { - $db.start-transaction; # start a new transaction - KEEP $db.commit; # commit the transaction if all went well - UNDO $db.rollback; # or rollback if all hell broke loose + $db.start-transaction; # start a new transaction + KEEP $db.commit; # commit the transaction if all went well + UNDO $db.rollback; # or rollback if all hell broke loose } ``` ## Statement prefixes ```perl6 -## Those act a bit like phasers: they affect the behavior of the following code. -## Though, they run in-line with the executable code, so they're in lowercase. -## (`try` and `start` are theoretically in that list, but explained elsewhere) -## Note: all of these (except start) don't need explicit brackets `{` and `}`. +## Those act a bit like phasers: they affect the behavior of the following +## code. Though, they run in-line with the executable code, so they're in +## lowercase. (`try` and `start` are theoretically in that list, but explained +## elsewhere) Note: all of these (except start) don't need explicit curly +## braces `{` and `}`. -## - `do` (that you already saw) - runs a block or a statement as a term -## You can't normally use a statement as a value (or "term"): -## -## my $value = if True { 1 } # `if` is a statement - parse error -## -## This works: -my $a = do if True { 5 } # with `do`, `if` is now a term. - -## - `once` - Makes sure a piece of code only runs once -for ^5 { once say 1 }; #=> 1 - # Only prints ... once. -## Like `state`, they're cloned per-scope -for ^5 { sub { once say 1 }() } #=> 1 1 1 1 1 - # Prints once per lexical scope - -## - `gather` - Co-routine thread -## Gather allows you to `take` several values in an array, -## much like `do`, but allows you to take any expression. +## `do` - (which you already saw) runs a block or a statement as a term. +## Normally you cannot use a statement as a value (or "term"). `do` helps us +## do it. + +# my $value = if True { 1 } # this fails since `if` is a statement +my $a = do if True { 5 } # with `do`, `if` is now a term returning a value + +## `once` - makes sure a piece of code only runs once. +for ^5 { + once say 1 +}; #=> 1, only prints ... once + +## Similar to `state`, they're cloned per-scope. +for ^5 { + sub { once say 1 }() +}; #=> 1 1 1 1 1, prints once per lexical scope. + +## `gather` - co-routine thread. The `gather` constructs allows us to `take` +## several values from an array/list, much like `do`. say gather for ^5 { - take $_ * 3 - 1; - take $_ * 3 + 1; -} #=> -1 1 2 4 5 7 8 10 11 13 + take $_ * 3 - 1; + take $_ * 3 + 1; +} +#=> -1 1 2 4 5 7 8 10 11 13 + say join ',', gather if False { - take 1; - take 2; - take 3; -} # Doesn't print anything. + take 1; + take 2; + take 3; +} +# Doesn't print anything. -## - `eager` - Evaluate statement eagerly (forces eager context) +## `eager` - evaluates a statement eagerly (forces eager context) ## Don't try this at home: -## -## eager 1..*; # this will probably hang for a while (and might crash ...). -## +# eager 1..*; # this will probably hang for a while (and might crash ...). ## But consider: constant thrice = gather for ^3 { say take $_ }; # Doesn't print anything - ## versus: constant thrice = eager gather for ^3 { say take $_ }; #=> 0 1 2 ``` @@ -1207,102 +1366,105 @@ constant thrice = eager gather for ^3 { say take $_ }; #=> 0 1 2 ## Iterables ```perl6 -## Iterables are objects that can be iterated similar to the `for` construct -## `flat`, flattens iterables: -say (1, 10, (20, 10) ); #> (1 10 (20 10)) Notice how grouping is maintained -say (1, 10, (20, 10) ).flat; #> (1 10 20 10) Now the iterable is flat +## Iterables are objects that can be iterated over which are +## are similar to the `for` construct. -## - `lazy` - Defer actual evaluation until value is fetched -## (forces lazy context) +## `flat` - flattens iterables. +say (1, 10, (20, 10) ); #=> (1 10 (20 10)), notice how neste lists are + # preserved +say (1, 10, (20, 10) ).flat; #=> (1 10 20 10), now the iterable is flat + +## - `lazy` - defers actual evaluation until value is fetched by forcing +## lazy context. my @lazy-array = (1..100).lazy; -say @lazy-array.is-lazy; #> True # Check for laziness with the `is-lazy` method. -say @lazy-array; #> [...] List has not been iterated on! +say @lazy-array.is-lazy; #=> True, check for laziness with the `is-lazy` method. +say @lazy-array; #=> [...] List has not been iterated on! my @lazy-array { .print }; # This works and will only do as much work as # is needed. -[//]: # ( TODO explain that gather/take and map are all lazy) -## - `sink` - An `eager` that discards the results (forces sink context) + +# ( **TODO** explain that gather/take and map are all lazy) + +## `sink` - an `eager` that discards the results by forcing sink context. constant nilthingie = sink for ^3 { .say } #=> 0 1 2 -say nilthingie.perl; #=> Nil +say nilthingie.perl; #=> Nil -## - `quietly` blocks will suppress warnings: +## `quietly` - suppresses warnings in blocks. quietly { warn 'This is a warning!' }; #=> No output -## - `contend` - Attempts side effects under STM -## Not yet implemented ! +## `contend` - attempts side effects under STM +## Not yet implemented! ``` -## More operators thingies ! +## More operators thingies! ```perl6 -## Everybody loves operators ! Let's get more of them +## Everybody loves operators! Let's get more of them. ## The precedence list can be found here: ## https://docs.perl6.org/language/operators#Operator_Precedence ## But first, we need a little explanation about associativity: -## * Binary operators: +## Binary operators: $a ! $b ! $c; # with a left-associative `!`, this is `($a ! $b) ! $c` $a ! $b ! $c; # with a right-associative `!`, this is `$a ! ($b ! $c)` $a ! $b ! $c; # with a non-associative `!`, this is illegal $a ! $b ! $c; # with a chain-associative `!`, this is `($a ! $b) and ($b ! $c)` $a ! $b ! $c; # with a list-associative `!`, this is `infix:<>` -## * Unary operators: +## Unary operators: !$a! # with left-associative `!`, this is `(!$a)!` !$a! # with right-associative `!`, this is `!($a!)` !$a! # with non-associative `!`, this is illegal ``` -### Create your own operators ! +### Create your own operators! ```perl6 -## Okay, you've been reading all of that, so I guess I should try -## to show you something exciting. -## I'll tell you a little secret (or not-so-secret): +## Okay, you've been reading all of that, so you might want to try something +## more exciting?! I'll tell you a little secret (or not-so-secret): ## In Perl 6, all operators are actually just funny-looking subroutines. ## You can declare an operator just like you declare a sub: -sub prefix:<win>($winner) { # refer to the operator categories - # (yes, it's the "words operator" `<>`) - say "$winner Won !"; +# prefix refers to the operator categories (prefix, infix, postfix, etc). +sub prefix:<win>( $winner ) { + say "$winner Won!"; } -win "The King"; #=> The King Won ! - # (prefix is before) +win "The King"; #=> The King Won! + # (prefix means 'before') ## you can still call the sub with its "full name": -say prefix:<!>(True); #=> False +say prefix:<!>(True); #=> False +prefix:<win>("The Queen"); #=> The Queen Won! -sub postfix:<!>(Int $n) { - [*] 2..$n; # using the reduce meta-operator ... See below ;-) ! +sub postfix:<!>( Int $n ) { + [*] 2..$n; # using the reduce meta-operator... See below ;-)! } say 5!; #=> 120 - # Postfix operators (after) have to come *directly* after the term. + # Postfix operators ('after') have to come *directly* after the term. # No whitespace. You can use parentheses to disambiguate, i.e. `(5!)!` - -sub infix:<times>(Int $n, Block $r) { # infix in the middle - for ^$n { - $r(); # You need the explicit parentheses to call the function in `$r`, - # else you'd be referring at the variable itself, like with `&r`. - } +sub infix:<times>( Int $n, Block $r ) { # infix ('between') + for ^$n { + $r(); # You need the explicit parentheses to call the function in `$r`, + # else you'd be referring at the variable itself, like with `&r`. + } } 3 times -> { say "hello" }; #=> hello #=> hello #=> hello - # You're very recommended to put spaces - # around your infix operator calls. +## It's recommended to put spaces around your +## infix operator calls. ## For circumfix and post-circumfix ones -sub circumfix:<[ ]>(Int $n) { - $n ** $n +sub circumfix:<[ ]>( Int $n ) { + $n ** $n } say [5]; #=> 3125 - # circumfix is around. Again, no whitespace. + # circumfix means 'around'. Again, no whitespace. -sub postcircumfix:<{ }>(Str $s, Int $idx) { - ## post-circumfix is - ## "after a term, around something" - $s.substr($idx, 1); +sub postcircumfix:<{ }>( Str $s, Int $idx ) { + ## post-circumfix is 'after a term, around something' + $s.substr($idx, 1); } say "abc"{1}; #=> b # after the term `"abc"`, and around the index (1) @@ -1312,47 +1474,47 @@ say "abc"{1}; #=> b ## (a simple named argument underneath): %h{$key}:delete; ## equivalent to: -postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that) +postcircumfix:<{ }>( %h, $key, :delete ); # (you can call operators like this) -## It's *all* using the same building blocks! -## Syntactic categories (prefix infix ...), named arguments (adverbs), ..., -## - used to build the language - are available to you. -## (you are, obviously, recommended against making an operator out of -## *everything* -- with great power comes great responsibility) +## It's *all* using the same building blocks! Syntactic categories +## (prefix infix ...), named arguments (adverbs), ..., etc. used to build +## the language - are available to you. Obviously, you're advised against +## making an operator out of *everything* -- with great power comes great +## responsibility. ``` -### Meta operators ! +### Meta operators! ```perl6 -## Oh boy, get ready. Get ready, because we're delving deep -## into the rabbit's hole, and you probably won't want to go -## back to other languages after reading that. -## (I'm guessing you don't want to already at that point). +## Oh boy, get ready!. Get ready, because we're delving deep into the rabbit's +## hole, and you probably won't want to go back to other languages after +## reading this. (I'm guessing you don't want to go back at this point but +## let's continue, for the journey is long and enjoyable!). + ## Meta-operators, as their name suggests, are *composed* operators. -## Basically, they're operators that apply another operator. +## Basically, they're operators that act on another operators. + +## The reduce meta-operator is a prefix meta-operator that takes a binary +## function and one or many lists. If it doesn't get passed any argument, +## it either returns a "default value" for this operator (a meaningless value) +## or `Any` if there's none (examples below). Otherwise, it pops an element +## from the list(s) one at a time, and applies the binary function to the last +## result (or the list's first element) and the popped element. -## * Reduce meta-operator -## It's a prefix meta-operator that takes a binary function and -## one or many lists. If it doesn't get passed any argument, -## it either returns a "default value" for this operator -## (a meaningless value) or `Any` if there's none (examples below). -## -## Otherwise, it pops an element from the list(s) one at a time, and applies -## the binary function to the last result (or the list's first element) -## and the popped element. -## ## To sum a list, you could use the reduce meta-operator with `+`, i.e.: -say [+] 1, 2, 3; #=> 6 -## equivalent to `(1+2)+3` +say [+] 1, 2, 3; #=> 6, equivalent to (1+2)+3. -say [*] 1..5; #=> 120 -## equivalent to `((((1*2)*3)*4)*5)`. +## To multiply a list +say [*] 1..5; #=> 120, equivalent to ((((1*2)*3)*4)*5). ## You can reduce with any operator, not just with mathematical ones. -## For example, you could reduce with `//` to get -## the first defined element of a list: -say [//] Nil, Any, False, 1, 5; #=> False - # (Falsey, but still defined) +## For example, you could reduce with `//` to get first defined element +## of a list: +say [//] Nil, Any, False, 1, 5; #=> False + # (Falsey, but still defined) +## Or with relational operators, i.e., `>` to check elements of a list +## are ordered accordingly: +say say [>] 234, 156, 6, 3, -20; #=> True ## Default value examples: say [*] (); #=> 1 @@ -1365,15 +1527,14 @@ say [//]; #=> (Any) sub add($a, $b) { $a + $b } say [[&add]] 1, 2, 3; #=> 6 -## * Zip meta-operator -## This one is an infix meta-operator that also can be used as a "normal" -## operator. It takes an optional binary function (by default, it just creates -## a pair), and will pop one value off of each array and call its binary -## function on these until it runs out of elements. It returns an array with -## all of these new elements. -(1, 2) Z (3, 4); # ((1, 3), (2, 4)), since by default, the function - # makes an array. -1..3 Z+ 4..6; # (5, 7, 9), using the custom infix:<+> function +## The zip meta-operator is an infix meta-operator that also can be used as a +## "normal" operator. It takes an optional binary function (by default, it +## just creates a pair), and will pop one value off of each array and call +## its binary function on these until it runs out of elements. It returns an +## array with all of these new elements. +say (1, 2) Z (3, 4); #=> ((1, 3), (2, 4)), since by default the function + # makes an array. +say 1..3 Z+ 4..6; #=> (5, 7, 9), using the custom infix:<+> function ## Since `Z` is list-associative (see the list above), ## you can use it on more than one list @@ -1385,252 +1546,258 @@ say [[&add]] 1, 2, 3; #=> 6 ## And to end the operator list: -## * Sequence operator ## The sequence operator is one of Perl 6's most powerful features: ## it's composed of first, on the left, the list you want Perl 6 to deduce from ## (and might include a closure), and on the right, a value or the predicate -## that says when to stop (or Whatever for a lazy infinite list). -my @list = 1, 2, 3 ... 10; # basic deducing -#my @list = 1, 3, 6 ... 10; # this dies because Perl 6 can't figure out the end -my @list = 1, 2, 3 ...^ 10; # as with ranges, you can exclude the last element - # (the iteration when the predicate matches). -my @list = 1, 3, 9 ... * > 30; # you can use a predicate - # (with the Whatever Star, here). -my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalent to the above) - -my @fib = 1, 1, *+* ... *; # lazy infinite list of fibonacci series, - # computed using a closure! +## that says when to stop (or a Whatever Star for a lazy infinite list). + +my @list = 1, 2, 3...10; # basic arithmetic sequence +# my @list = 1, 3, 6...10; # this dies because Perl 6 can't figure out the end +my @list = 1, 2, 3...^10; # as with ranges, you can exclude the last element + # (the iteration ends when the predicate matches). +my @list = 1, 3, 9...* > 30; # you can use a predicate (with the Whatever Star). +my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalent to the above + # using a block here). + +my @fib = 1, 1, *+* ... *; # lazy infinite list of fibonacci sequence, + # computed using a closure! my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalent to the above) -my @fib = 1, 1, { $^a + $^b } ... *; #(... also equivalent to the above) +my @fib = 1, 1, { $^a + $^b } ... *; # (also equivalent to the above) ## $a and $b will always take the previous values, meaning here -## they'll start with $a = 1 and $b = 1 (values we set by hand). -## then $a = 1 and $b = 2 (result from previous $a+$b), and so on. +## they'll start with $a = 1 and $b = 1 (values we set by hand), +## then $a = 1 and $b = 2 (result from previous $a+$b), and so on. say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 # (using a range as the index) -## Note : as for ranges, once reified, elements aren't re-calculated. +## Note: as for ranges, once reified, elements aren't re-calculated. ## That's why `@primes[^100]` will take a long time the first time you print -## it, then be instant. +## it, then will be instateneous. ``` ## Regular Expressions ```perl6 -## I'm sure a lot of you have been waiting for this one. -## Well, now that you know a good deal of Perl 6 already, we can get started. -## First off, you'll have to forget about "PCRE regexps" (perl-compatible -## regexps). +## I'm sure a lot of you have been waiting for this one. Well, now that you know +## a good deal of Perl 6 already, we can get started. First off, you'll have to +## forget about "PCRE regexps" (perl-compatible regexps). ## -## IMPORTANT: Don't skip them because you know PCRE. They're different. -## Some things are the same (like `?`, `+`, and `*`), -## but sometimes the semantics change (`|`). -## Make sure you read carefully, because you might trip over a new behavior. +## IMPORTANT: Don't skip them because you know PCRE. They're different. Some +## things are the same (like `?`, `+`, and `*`), but sometimes the semantics +## change (`|`). Make sure you read carefully, because you might trip over a +## new behavior. ## ## Perl 6 has many features related to RegExps. After all, Rakudo parses itself. -## We're first going to look at the syntax itself, -## then talk about grammars (PEG-like), differences between -## `token`, `regex` and `rule` declarators, and some more. -## Side note: you still have access to PCRE regexps using the `:P5` modifier. -## (we won't be discussing this in this tutorial, however) +## We're first going to look at the syntax itself, then talk about grammars +## (PEG-like), differences between `token`, `regex` and `rule` declarators, +## and some more. Side note: you still have access to PCRE regexps using the +## `:P5` modifier which we won't be discussing this in this tutorial, though. ## ## In essence, Perl 6 natively implements PEG ("Parsing Expression Grammars"). ## The pecking order for ambiguous parses is determined by a multi-level -## tie-breaking test: -## - Longest token matching. `foo\s+` beats `foo` (by 2 or more positions) -## - Longest literal prefix. `food\w*` beats `foo\w*` (by 1) +## tie-breaking test: +## - Longest token matching: `foo\s+` beats `foo` (by 2 or more positions) +## - Longest literal prefix: `food\w*` beats `foo\w*` (by 1) ## - Declaration from most-derived to less derived grammars -## (grammars are actually classes) +## (grammars are actually classes) ## - Earliest declaration wins -say so 'a' ~~ /a/; #=> True -say so 'a' ~~ / a /; #=> True # More readable with some spaces! +say so 'a' ~~ /a/; #=> True +say so 'a' ~~ / a /; #=> True, more readable with some spaces! ## In all our examples, we're going to use the smart-matching operator against -## a regexp. We're converting the result using `so`, but in fact, it's -## returning a `Match` object. They know how to respond to list indexing, -## hash indexing, and return the matched string. -## The results of the match are available as `$/` (implicitly lexically-scoped). -## You can also use the capture variables which start at 0: -## `$0`, `$1', `$2`... +## a regexp. We're converting the result using `so` to a Boolean value because, +## in fact, it's returning a `Match` object. They know how to respond to list +## indexing, hash indexing, and return the matched string. The results of the +## match are available in the `$/` variable (implicitly lexically-scoped). You +## can also use the capture variables which start at 0: `$0`, `$1', `$2`... ## -## You can also note that `~~` does not perform start/end checking -## (meaning the regexp can be matched with just one char of the string), -## we're going to explain later how you can do it. - -## In Perl 6, you can have any alphanumeric as a literal, -## everything else has to be escaped, using a backslash or quotes. -say so 'a|b' ~~ / a '|' b /; # `True`. Wouldn't mean the same if `|` wasn't - # escaped -say so 'a|b' ~~ / a \| b /; # `True`. Another way to escape it. - -## The whitespace in a regexp is actually not significant, -## unless you use the `:s` (`:sigspace`, significant space) adverb. -say so 'a b c' ~~ / a b c /; #> `False`. Space is not significant here -say so 'a b c' ~~ /:s a b c /; #> `True`. We added the modifier `:s` here. +## You can also note that `~~` does not perform start/end checking, meaning +## the regexp can be matched with just one character of the string. We'll +## explain later how you can do it. + +## In Perl 6, you can have any alphanumeric as a literal, everything else has +## to be escaped by using a backslash or quotes. +say so 'a|b' ~~ / a '|' b /; #=> `True`, it wouldn't mean the same thing if + # `|` wasn't escaped. +say so 'a|b' ~~ / a \| b /; #=> `True`, another way to escape it. + +## The whitespace in a regexp is actually not significant, unless you use the +## `:s` (`:sigspace`, significant space) adverb. +say so 'a b c' ~~ / a b c /; #=> `False`, space is not significant here! +say so 'a b c' ~~ /:s a b c /; #=> `True`, we added the modifier `:s` here. + ## If we use only one space between strings in a regex, Perl 6 will warn us: -say so 'a b c' ~~ / a b c /; #> 'False' #> Space is not significant here; -## please use quotes or :s (:sigspace) modifier (or, to suppress this warning, -## omit the space, or otherwise change the spacing) -## To fix this and make the spaces less ambiguous, either use at least two -## spaces between strings or use the `:s` adverb. +say so 'a b c' ~~ / a b c /; #=> `False`, with warning about space +say so 'a b c' ~~ / a b c /; #=> `False` + +## Please use quotes or :s (:sigspace) modifier (or, to suppress this warning, +## omit the space, or otherwise change the spacing). To fix this and make the +## spaces less ambiguous, either use at least two spaces between strings +## or use the `:s` adverb. -## As we saw before, we can embed the `:s` inside the slash delimiters, but we +## As we saw before, we can embed the `:s` inside the slash delimiters, but we ## can also put it outside of them if we specify `m` for 'match': -say so 'a b c' ~~ m:s/a b c/; #> `True` -## By using `m` to specify 'match', we can also use delimiters other -## than slashes: -say so 'abc' ~~ m{a b c}; #> `True` +say so 'a b c' ~~ m:s/a b c/; #=> `True` + +## By using `m` to specify 'match', we can also use delimiters other than +## slashes: +say so 'abc' ~~ m{a b c}; #=> `True` +say so 'abc' ~~ m[a b c]; #=> `True` +# m/.../ is equivalent to /.../ ## Use the :i adverb to specify case insensitivity: -say so 'ABC' ~~ m:i{a b c}; #> `True` +say so 'ABC' ~~ m:i{a b c}; #=> `True` -## It is, however, important as for how modifiers (that you're gonna see just -## below) are applied ... +## However, whitespace is important as for how modifiers are applied ( +## (which you'll see just below) ... ## Quantifying - `?`, `+`, `*` and `**`. -## - `?` - 0 or 1 -so 'ac' ~~ / a b c /; # `False` -so 'ac' ~~ / a b? c /; # `True`, the "b" matched 0 times. -so 'abc' ~~ / a b? c /; # `True`, the "b" matched 1 time. +## `?` - zero or one match +so 'ac' ~~ / a b c /; #=> `False` +so 'ac' ~~ / a b? c /; #=> `True`, the "b" matched 0 times. +so 'abc' ~~ / a b? c /; #=> `True`, the "b" matched 1 time. -## ... As you read just before, whitespace is important because it determines -## which part of the regexp is the target of the modifier: -so 'def' ~~ / a b c? /; # `False`. Only the `c` is optional -so 'def' ~~ / a b? c /; # `False`. Whitespace is not significant -so 'def' ~~ / 'abc'? /; # `True`. The whole "abc" group is optional. +## ...As you read before, whitespace is important because it determines which +## part of the regexp is the target of the modifier: +so 'def' ~~ / a b c? /; #=> `False`, only the `c` is optional +so 'def' ~~ / a b? c /; #=> `False`, whitespace is not significant +so 'def' ~~ / 'abc'? /; #=> `True`, the whole "abc" group is optional ## Here (and below) the quantifier applies only to the `b` -## - `+` - 1 or more -so 'ac' ~~ / a b+ c /; # `False`; `+` wants at least one matching -so 'abc' ~~ / a b+ c /; # `True`; one is enough -so 'abbbbc' ~~ / a b+ c /; # `True`, matched 4 "b"s - -## - `*` - 0 or more -so 'ac' ~~ / a b* c /; # `True`, they're all optional. -so 'abc' ~~ / a b* c /; # `True` -so 'abbbbc' ~~ / a b* c /; # `True` -so 'aec' ~~ / a b* c /; # `False`. "b"(s) are optional, not replaceable. - -## - `**` - (Unbound) Quantifier -## If you squint hard enough, you might understand -## why exponentation is used for quantity. -so 'abc' ~~ / a b**1 c /; # `True` (exactly one time) -so 'abc' ~~ / a b**1..3 c /; # `True` (one to three times) -so 'abbbc' ~~ / a b**1..3 c /; # `True` -so 'abbbbbbc' ~~ / a b**1..3 c /; # `False` (too much) -so 'abbbbbbc' ~~ / a b**3..* c /; # `True` (infinite ranges are okay) - -## - `<[]>` - Character classes -## Character classes are the equivalent of PCRE's `[]` classes, but -## they use a more perl6-ish syntax: -say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' +## `+` - one or more matches +so 'ac' ~~ / a b+ c /; #=> `False`, `+` wants at least one matching +so 'abc' ~~ / a b+ c /; #=> `True`, one is enough +so 'abbbbc' ~~ / a b+ c /; #=> `True`, matched 4 "b"s + +## `*` - zero or more matches +so 'ac' ~~ / a b* c /; #=> `True`, they're all optional. +so 'abc' ~~ / a b* c /; #=> `True` +so 'abbbbc' ~~ / a b* c /; #=> `True` +so 'aec' ~~ / a b* c /; #=> `False`. "b"(s) are optional, not replaceable. + +## `**` - (Unbound) Quantifier +## If you squint hard enough, you might understand why exponentation is used +## for quantity. +so 'abc' ~~ / a b**1 c /; #=> `True`, (exactly one time) +so 'abc' ~~ / a b**1..3 c /; #=> `True`, (one to three times) +so 'abbbc' ~~ / a b**1..3 c /; #=> `True` +so 'abbbbbbc' ~~ / a b**1..3 c /; #=> `False, (too much) +so 'abbbbbbc' ~~ / a b**3..* c /; #=> `True`, (infinite ranges are okay) + +## `<[]>` - Character classes +## Character classes are the equivalent of PCRE's `[]` classes, but they use a +## more perl6-ish syntax: +say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' ## You can use ranges: say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae' -## Just like in normal regexes, if you want to use a special character, -## escape it (the last one is escaping a space) +## Just like in normal regexes, if you want to use a special character, escape +## it (the last one is escaping a space which would be equivalent to using +## ' '): say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !' -## You'll get a warning if you put duplicate names -## (which has the nice effect of catching the wrote quoting:) -'he he' ~~ / <[ h e ' ' ]> /; # Warns "Repeated characters found in characters - # class" +## You'll get a warning if you put duplicate names (which has the nice effect +## of catching the raw quoting): +'he he' ~~ / <[ h e ' ' ]> /; +# Warns "Repeated character (') unexpectedly found in character class" -## You can also negate them ... (equivalent to `[^]` in PCRE) -so 'foo' ~~ / <-[ f o ]> + /; # False +## You can also negate character classes... (`<-[]>` equivalent to `[^]` in PCRE) +so 'foo' ~~ / <-[ f o ]> + /; #=> False -## ... and compose them: : -so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # False (any letter except f and o) -so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # True (no letter except f and o) -so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (the + doesn't replace the +## ... and compose them: +so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; #=> `False`, (any letter except f and o) +so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (no letter except f and o) +so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (the + doesn't replace the # left part) ``` ### Grouping and capturing ```perl6 -## Group: you can group parts of your regexp with `[]`. -## These groups are *not* captured (like PCRE's `(?:)`). -so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing +## Group: you can group parts of your regexp with `[]`. Unlike PCRE's `(?:)`, +## these groups are *not* captured. +so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; -## The previous line returns `True`. -## We match the "012" 1 or more time (the `+` was applied to the group). + +## The previous line returns `True`. The regex matches "012" 1 or more time +## (achieved by the the `+` applied to the group). ## But this does not go far enough, because we can't actually get back what ## we matched. -## Capture: We can actually *capture* the results of the regexp, -## using parentheses. + +## Capture: The results of a regexp can be *captured* by using parentheses. so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (using `so` # here, `$/` below) ## So, starting with the grouping explanations. -## As we said before, our `Match` object is available as `$/`: -say $/; # Will print some weird stuff (we'll explain) (or "Nil" if - # nothing matched). +## As we said before, our `Match` object is stored inside the `$/` variable: +say $/; # Will either print some weird stuff or `Nil` if nothing matched. ## As we also said before, it has array indexing: say $/[0]; #=> 「ABC」 「ABC」 - # These weird brackets are `Match` objects. + # These corner brackets are `Match` objects. # Here, we have an array of these. -say $0; # The same as above. +say $0; # The same as above. -## Our capture is `$0` because it's the first and only one capture in the +## Our capture is `$0` because it's the first and only one capture in the ## regexp. You might be wondering why it's an array, and the answer is simple: -## Some capture (indexed using `$0`, `$/[0]` or a named one) will be an array -## IFF it can have more than one element -## (so, with `*`, `+` and `**` (whatever the operands), but not with `?`). +## Some captures (indexed using `$0`, `$/[0]` or a named one) will be an array +## if and only if they can have more than one element. Thus any capture with +## `*`, `+` and `**` (whatever the operands), but not with `?`. ## Let's use examples to see that: ## Note: We quoted A B C to demonstrate that the whitespace between them isn't -## significant. If we want the whitespace to *be* significant there, we +## significant. If we want the whitespace to *be* significant there, we ## can use the :sigspace modifier. -so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # `True` -say $/[0]; #=> 「ABC」 +say so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; #=> `True` +say $/[0]; #=> 「ABC」 say $0.WHAT; #=> (Match) # There can't be more than one, so it's only a single match object. -so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True +say so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True say $0.WHAT; #=> (Any) # This capture did not match, so it's empty -so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; # `True` +so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; #=> `True` say $0.WHAT; #=> (Array) # A specific quantifier will always capture an Array, - # may it be a range or a specific value (even 1). + # be a range or a specific value (even 1). -## The captures are indexed per nesting. This means a group in a group will be +## The captures are indexed per nesting. This means a group in a group will be ## nested under its parent group: `$/[0][0]`, for this code: 'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; -say $/[0].Str; #=> hello~ +say $/[0].Str; #=> hello~ say $/[0][0].Str; #=> ~ -## This stems from a very simple fact: `$/` does not contain strings, integers -## or arrays, it only contains match objects. These contain the `.list`, `.hash` -## and `.Str` methods. (but you can also just use `match<key>` for hash access -## and `match[idx]` for array access) +## This stems from a very simple fact: `$/` does not contain strings, integers +## or arrays, it only contains Match objects. These contain the `.list`, `.hash` +## and `.Str` methods but you can also just use `match<key>` for hash access +## and `match[idx]` for array access. say $/[0].list.perl; #=> (Match.new(...),).list - # We can see it's a list of Match objects. Those contain - # a bunch of infos: where the match started/ended, - # the "ast" (see actions later), etc. + # We can see it's a list of Match objects. These contain + # a bunch of info: where the match started/ended, + # the "ast" (see actions later), etc. # You'll see named capture below with grammars. -## Alternatives - the `or` of regexps +## Alternation - the `or` of regexps ## WARNING: They are DIFFERENT from PCRE regexps. -so 'abc' ~~ / a [ b | y ] c /; # `True`. Either "b" or "y". -so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviously enough ... - -## The difference between this `|` and the one you're used to is LTM. -## LTM means "Longest Token Matching". This means that the engine will always -## try to match as much as possible in the strng -'foo' ~~ / fo | foo /; # `foo`, because it's longer. -## To decide which part is the "longest", it first splits the regex in +say so 'abc' ~~ / a [ b | y ] c /; #=> `True`. Either "b" or "y". +say so 'ayc' ~~ / a [ b | y ] c /; #=> `True`. Obviously enough... + +## The difference between this `|` and the one you're used to is +## LTM ("Longest Token Matching"). This means that the engine will always +## try to match as much as possible in the string. +say 'foo' ~~ / fo | foo /; #=> `foo`, instead of `fo`, because it's longer. + +## To decide which part is the "longest", it first splits the regex in ## two parts: ## The "declarative prefix" (the part that can be statically analyzed) -## and the procedural parts. -## Declarative prefixes include alternations (`|`), conjunctions (`&`), -## sub-rule calls (not yet introduced), literals, characters classes and +## and the procedural parts: +## - The declarative prefixes include alternations (`|`), conjunctions (`&`), +## sub-rule calls (not yet introduced), literals, characters classes and ## quantifiers. -## The latter include everything else: back-references, code assertions, -## and other things that can't traditionnaly be represented by normal regexps. +## - The procedural part include everything else: back-references, +## code assertions, and other things that can't traditionnaly be represented +## by normal regexps. ## ## Then, all the alternatives are tried at once, and the longest wins. ## Examples: @@ -1639,109 +1806,110 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviously enough ... ## DECLARATIVE (nested groups are not a problem) / \s* [ \w & b ] [ c | d ] /; ## However, closures and recursion (of named regexps) are procedural. -## ... There are also more complicated rules, like specificity -## (literals win over character classes) +## There are also more complicated rules, like specificity (literals win over +## character classes). ## Note: the first-matching `or` still exists, but is now spelled `||` -'foo' ~~ / fo || foo /; # `fo` now. +say 'foo' ~~ / fo || foo /; #=> `fo` now. ``` ## Extra: the MAIN subroutine ```perl6 -## The `MAIN` subroutine is called when you run a Perl 6 file directly. -## It's very powerful, because Perl 6 actually parses the arguments -## and pass them as such to the sub. It also handles named argument (`--foo`) -## and will even go as far as to autogenerate a `--help` -sub MAIN($name) { say "Hello, $name !" } +## The `MAIN` subroutine is called when you run a Perl 6 file directly. It's +## very powerful, because Perl 6 actually parses the arguments and pass them +## as such to the sub. It also handles named argument (`--foo`) and will even +## go as far as to autogenerate a `--help` flag. +sub MAIN($name) { + say "Hello, $name!"; +} ## This produces: -## $ perl6 cli.pl -## Usage: -## t.pl <name> +## $ perl6 cli.pl +## Usage: +## t.pl <name> ## And since it's a regular Perl 6 sub, you can have multi-dispatch: ## (using a "Bool" for the named argument so that we can do `--replace` -## instead of `--replace=1`) +## instead of `--replace=1`. The presence of `--replace` indicates truthness +## while its absence falseness). + subset File of Str where *.IO.d; # convert to IO object to check the file exists multi MAIN('add', $key, $value, Bool :$replace) { ... } multi MAIN('remove', $key) { ... } multi MAIN('import', File, Str :$as) { ... } # omitting parameter name + ## This produces: -## $ perl6 cli.pl -## Usage: -## t.pl [--replace] add <key> <value> -## t.pl remove <key> -## t.pl [--as=<Str>] import (File) -## As you can see, this is *very* powerful. -## It even went as far as to show inline the constants. -## (the type is only displayed if the argument is `$`/is named) +## $ perl6 cli.pl +## Usage: +## cli.p6 [--replace] add <key> <value> +## cli.p6 remove <key> +## cli.p6 [--as=<Str>] import <File> + +## As you can see, this is *very* powerful. It even went as far as to show inline +## the constants (the type is only displayed if the argument is `$`/is named). ``` ## APPENDIX A: ### List of things ```perl6 -## It's considered by now you know the Perl6 basics. -## This section is just here to list some common operations, -## but which are not in the "main part" of the tutorial to bloat it up +## It's assumed by now you know the Perl6 basics. This section is just here to +## list some common operations, but which are not in the "main part" of the +## tutorial to avoid bloating it up. ## Operators - -## * Sort comparison -## They return one value of the `Order` enum : `Less`, `Same` and `More` -## (which numerify to -1, 0 or +1). -1 <=> 4; # sort comparison for numerics -'a' leg 'b'; # sort comparison for string -$obj eqv $obj2; # sort comparison using eqv semantics - -## * Generic ordering -3 before 4; # True -'b' after 'a'; # True - -## * Short-circuit default operator -## Like `or` and `||`, but instead returns the first *defined* value : -say Any // Nil // 0 // 5; #=> 0 - -## * Short-circuit exclusive or (XOR) -## Returns `True` if one (and only one) of its arguments is true -say True ^^ False; #=> True -## * Flip Flop -## The flip flop operators (`ff` and `fff`, equivalent to P5's `..`/`...`). -## are operators that take two predicates to test: -## They are `False` until their left side returns `True`, then are `True` until -## their right side returns `True`. -## Like for ranges, you can exclude the iteration when it became `True`/`False` -## by using `^` on either side. -## Let's start with an example : +## Sort comparison - they return one value of the `Order` enum: `Less`, `Same` +## and `More` (which numerify to -1, 0 or +1 respectively). +1 <=> 4; # sort comparison for numerics +'a' leg 'b'; # sort comparison for string +$obj eqv $obj2; # sort comparison using eqv semantics + +## Generic ordering +3 before 4; # True +'b' after 'a'; # True + +## Short-circuit default operator - similar to `or` and `||`, but instead +## returns the first *defined* value: +say Any // Nil // 0 // 5; #=> 0 + +## Short-circuit exclusive or (XOR) - returns `True` if one (and only one) of +## its arguments is true +say True ^^ False; #=> True + +## Flip flops - these operators (`ff` and `fff`, equivalent to P5's `..` +## and `...`) are operators that take two predicates to test: They are `False` +## until their left side returns `True`, then are `True` until their right +## side returns `True`. Similar to ranges, you can exclude the iteration when +## it become `True`/`False` by using `^` on either side. Let's start with an +## example : for <well met young hero we shall meet later> { - # by default, `ff`/`fff` smart-match (`~~`) against `$_`: - if 'met' ^ff 'meet' { # Won't enter the if for "met" - # (explained in details below). - .say - } + # by default, `ff`/`fff` smart-match (`~~`) against `$_`: + if 'met' ^ff 'meet' { # Won't enter the if for "met" + .say # (explained in details below). + } - if rand == 0 ff rand == 1 { # compare variables other than `$_` - say "This ... probably will never run ..."; - } + if rand == 0 ff rand == 1 { # compare variables other than `$_` + say "This ... probably will never run ..."; + } } -## This will print "young hero we shall meet" (excluding "met"): -## the flip-flop will start returning `True` when it first encounters "met" -## (but will still return `False` for "met" itself, due to the leading `^` -## on `ff`), until it sees "meet", which is when it'll start returning `False`. - -## The difference between `ff` (awk-style) and `fff` (sed-style) is that -## `ff` will test its right side right when its left side changes to `True`, -## and can get back to `False` right away -## (*except* it'll be `True` for the iteration that matched) - -## While `fff` will wait for the next iteration to -## try its right side, once its left side changed: + +## This will print "young hero we shall meet" (excluding "met"): the flip-flop +## will start returning `True` when it first encounters "met" (but will still +## return `False` for "met" itself, due to the leading `^` on `ff`), until it +## sees "meet", which is when it'll start returning `False`. + +## The difference between `ff` (awk-style) and `fff` (sed-style) is that `ff` +## will test its right side right when its left side changes to `True`, and can +## get back to `False` right away (*except* it'll be `True` for the iteration +## that matched) while `fff` will wait for the next iteration to try its right +## side, once its left side changed: .say if 'B' ff 'B' for <A B C B A>; #=> B B # because the right-hand-side was tested # directly (and returned `True`). - # "B"s are printed since it matched that - # time (it just went back to `False` + # "B"s are printed since it matched that + # time (it just went back to `False` # right away). .say if 'B' fff 'B' for <A B C B A>; #=> B C B # The right-hand-side wasn't tested until @@ -1750,50 +1918,49 @@ for <well met young hero we shall meet later> { ## A flip-flop can change state as many times as needed: for <test start print it stop not printing start print again stop not anymore> { - .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # exclude both "start" and "stop", - #=> "print it print again" + .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # exclude both "start" and "stop", + #=> "print it print again" } -## You might also use a Whatever Star, -## which is equivalent to `True` for the left side or `False` for the right: +## You might also use a Whatever Star, which is equivalent to `True` for the +## left side or `False` for the right: for (1, 3, 60, 3, 40, 60) { # Note: the parenthesis are superfluous here # (sometimes called "superstitious parentheses") - .say if $_ > 50 ff *; # Once the flip-flop reaches a number greater than 50, - # it'll never go back to `False` - #=> 60 3 40 60 + .say if $_ > 50 ff *; # Once the flip-flop reaches a number greater + # than 50, it'll never go back to `False` + #=> 60 3 40 60 } -## You can also use this property to create an `If` -## that'll not go through the first time : +## You can also use this property to create an `if` that'll not go through the +## first time: for <a b c> { - .say if * ^ff *; # the flip-flop is `True` and never goes back to `False`, - # but the `^` makes it *not run* on the first iteration - #=> b c + .say if * ^ff *; # the flip-flop is `True` and never goes back to `False`, + # but the `^` makes it *not run* on the first iteration + #=> b c } - -## - `===` is value identity and uses `.WHICH` on the objects to compare them -## - `=:=` is container identity and uses `VAR()` on the objects to compare them - +## The `===` operator is the value identity operator and uses `.WHICH` on the +## objects to compare them while `=:=` is the container identity operator +## and uses `VAR()` on the objects to compare them. ``` If you want to go further, you can: - Read the [Perl 6 Docs](https://docs.perl6.org/). This is a great - resource on Perl6. If you are looking for something, use the search bar. + resource on Perl6. If you are looking for something, use the search bar. This will give you a dropdown menu of all the pages referencing your search - term (Much better than using Google to find Perl 6 documents!) + term (Much better than using Google to find Perl 6 documents!). - Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This - is a great source of Perl 6 snippets and explanations. If the docs don't + is a great source of Perl 6 snippets and explanations. If the docs don't describe something well enough, you may find more detailed information here. This information may be a bit older but there are many great examples and - explanations. Posts stopped at the end of 2015 when the language was declared + explanations. Posts stopped at the end of 2015 when the language was declared stable and Perl 6.c was released. - - Come along on `#perl6` at `irc.freenode.net`. The folks here are + - Come along on `#perl6` at `irc.freenode.net`. The folks here are always helpful. - - Check the [source of Perl 6's functions and - classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is + - Check the [source of Perl 6's functions and + classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is mainly written in Perl 6 (with a lot of NQP, "Not Quite Perl", a Perl 6 subset easier to implement and optimize). - - Read [the language design documents](http://design.perl6.org). They explain + - Read [the language design documents](http://design.perl6.org). They explain P6 from an implementor point-of-view, but it's still very interesting. diff --git a/pl-pl/python-pl.html.markdown b/pl-pl/python-pl.html.markdown index 023c3e6b..222f753f 100644 --- a/pl-pl/python-pl.html.markdown +++ b/pl-pl/python-pl.html.markdown @@ -532,7 +532,7 @@ Czlowiek.grunt() # => "*grunt*" # Tak importuje się moduły: import math -print(math.sqrt(16)) # => 4 +print(math.sqrt(16)) # => 4.0 # Można podać konkretne funkcje, np. ceil, floor z modułu math from math import ceil, floor diff --git a/powershell.html.markdown b/powershell.html.markdown index f9c20607..db29bf96 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -245,7 +245,7 @@ function New-Website() { 'string' | gm # Syntax for calling static .NET methods -\[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') +[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') # Note that .NET functions MUST be called with parentheses # while PS functions CANNOT be called with parentheses. diff --git a/pt-br/asymptotic-notation-pt.html.markdown b/pt-br/asymptotic-notation-pt.html.markdown index 2f179f96..b70d26b7 100644 --- a/pt-br/asymptotic-notation-pt.html.markdown +++ b/pt-br/asymptotic-notation-pt.html.markdown @@ -13,7 +13,7 @@ lang: pt-br ## O que é? Notação Assintótica é uma linguagem que nos permite analisar o tempo de execução - de um algoritmo através da indentificação de seu comportamento com o + de um algoritmo através da identificação de seu comportamento com o crescimento da entrada oferecida. Isso também é conhecido como taxa de crescimento do algoritmo. O algoritmo de repente torna-se lento quando o tamanho da entrada cresce? O algoritmo mantém, em geral, seu tempo de execução @@ -33,12 +33,12 @@ Um modo seria contar o número de operações primitivas com diferentes tamanhos ## Tipos de Notação Assintótica -Na primeira seção desse documento, descrevemos como Notação Assintótica identifica o comportamento de um algoritmo +Na primeira seção deste documento, descrevemos como Notação Assintótica identifica o comportamento de um algoritmo a medida que o tamanho da entrada cresce. Imaginemos um algoritmo como uma função *f*, *n* como o tamanho da entrada e *f(n)* sendo o tempo de execução. Então, para dado algoritmo *f*, com entrada de tamanho *n*, você terá tempo de execução - *f(n)*. Isto resulta em um gráfico onde a coordernada Y é o tempo de execução -, a coordernada X representa o tamanho da entrada e os pontos representam o tempo + *f(n)*. Isto resulta em um gráfico onde a coordenada Y é o tempo de execução, + a coordenada X representa o tamanho da entrada e os pontos representam o tempo de execução para dado tamanho de entrada. Você pode representar a função, ou o algoritmo, com Notação Assintótica de várias @@ -49,7 +49,7 @@ não avalia o melhor caso, porque essas condições não são atingidas com freq Um bom exemplo disto seria em algoritmos de ordenação; especificamente, na adição de elementos à árvores. O melhor caso na maioria de algoritmos pode ser de apenas uma operação. Entretanto, na maioria dos casos, o elemento a ser adicionado terá -que percorrer a árvore de forma apropriada, o que pode causar a analise de um +que percorrer a árvore de forma apropriada, o que pode causar a análise de um ramo inteiro. Este é o pior caso, e isto é o que você está se preparando. @@ -63,16 +63,16 @@ Função Polinomial - an^z + . . . + an^2 + a*n^1 + a*n^0, onde *z* é uma const Função Exponencial - a^n, onde a é alguma constante ``` Estas são as funções básicas de crescimento usadas em várias notações. A lista - começa com a de crescimento mais lento (logarítima, a de execução mais rápida) + começa com a de crescimento mais lento (logarítmica, a de execução mais rápida) e segue para a de crescimento mais rápido (exponencial, de execução mais lenta). -Repare que enquando *n*, a entrada, cresce, cada uma dessas funções cresce mais -rápido que quadrático, polinimial e exponencial, comparadas com logaritma e linear. +Repare que enquanto *n*, a entrada, cresce, cada uma dessas funções cresce mais +rápido que quadrático, polinomial e exponencial, comparadas com logarítmica e linear. Uma nota extremamente importante para notações é tentar usar os termos mais simples. Isto significa descartar constantes e termos de ordem mais baixa, pois quando o tamanho da entrada cresce para o infinito (limites matemáticos), os termos de ordem mais baixa e constantes tornam-se irrelevantes. Por exemplo, se você tiver uma -constante muito grande, 2^9001, a simplificação não afeterá sua notação. +constante muito grande, 2^9001, a simplificação não afetará sua notação. Já que queremos as formas mais simples, mudemos nossa tabela um pouco... @@ -87,7 +87,7 @@ Função Exponencial - a^n, onde *a* é uma constante ### Big-O Big-O, também escrita como O, é uma Notação Assintótica para o pior caso. Digamos -*f(n)* seja o tempo de exeução de um algoritmo e *g(n)) um tempo de complexidade +*f(n)* seja o tempo de execução de um algoritmo e *g(n)) um tempo de complexidade arbitrário que você quer relacionar com seu algoritmo. *f(n)* é O(g(n)), se, para quando constante real c (c > 0), *f(n)* <= *c g(n)* para todo tamanho de entrada n (n > 0). @@ -116,7 +116,7 @@ Há alguma constante c que satisfaça a definição para todo n? 3log n + 100 <= 150 * log n, n > 2 (Indefinido em n = 1) ``` -Sim! A definição de Big-I for atentida, portante `f(n)` é `O(g(n))`. +Sim! A definição de Big-O foi atendida, portanto `f(n)` é `O(g(n))`. *Exemplo 2* @@ -146,7 +146,7 @@ Big-Omega, também escrita como Ω, é uma Notação Assintótica para o melhor Sinta-se livre para adicionar mais exemplos. Big-O é a notação primária usada para medir complexidade de algoritmos. ### Notas Finais -É difícil manter esse tipo de tópico curto e você deveria ler os livros e artigos listados abaixo. Eles cobrem muito mais profundamente definições e exemplos. Mais x='Algoritms & Data Structures' virá; teremos um documento sobre analisar código em breve. +É difícil manter esse tipo de tópico curto e você deveria ler os livros e artigos listados abaixo. Eles cobrem muito mais profundamente definições e exemplos. Mais x='Algorithms & Data Structures' virá; teremos um documento sobre analisar código em breve. ## Livros diff --git a/pt-br/pascal-pt.html.markdown b/pt-br/pascal-pt.html.markdown new file mode 100644 index 00000000..3a37271a --- /dev/null +++ b/pt-br/pascal-pt.html.markdown @@ -0,0 +1,253 @@ +--- +language: Pascal +filename: learnpascal-pt.pas +contributors: + - ["Ganesha Danu", "https://github.com/blinfoldking"] + - ["Keith Miyake", "https//github.com/kaymmm"] +translators: + - ["Raul Almeida", "https://github.com/almeidaraul"] +lang: pt-br +--- + + +>Pascal é uma linguagem de programação estruturada, que recebeu este nome em homenagem ao matemático e físico Blaise Pascal. Foi criada em 1970 pelo suíço Niklaus Wirth,tendo em mente encorajar o uso de código estruturado. +fonte : [wikipédia](https://pt.wikipedia.org/wiki/Pascal_(linguagem_de_programa%C3%A7%C3%A3o)) + + + +Para compilar e executar um programa em Pascal, você pode usar o freepascal, +um compilador gratuito. [Faça o download aqui](https://www.freepascal.org/) + +```pascal +//Corpo de um programa em Pascal +//isso é um comentário +{ + isso também é um comentário, + mas com várias linhas +} + +//cabeçalho do programa +PROGRAM aprendendo_pascal; //<-- não esqueça o ponto e vírgula. O nome do +programa deve começar com uma letra. + +CONST + { + aqui você declara valores constantes + } +TYPE + { + aqui você declara tipos não nativos + } +VAR + { + aqui você declara variáveis + } + +//programa de fato +BEGIN + 80 + aqui ficam todas as instruções que não pertencem nem a funções + nem a procedimentos + + blocos de código começam com BEGIN e terminam com END + (como as chaves em C) + } +END. //o "end" no final do programa requer um ponto final. +``` + +```pascal +//formas de declarar uma variável +VAR a:INTEGER; +VAR b:INTEGER; + +VAR + a : INTEGER; + b : INTEGER; + +VAR a,b : INTEGER; +``` + +```pascal +PROGRAM Learn_More; +//agora, mais sobre tipos de dados e operações + +CONST + PI = 3.141592654; + GNU = 'GNU''s Not Unix'; + { a convenção é usar caixa alta para constantes + + constantes têm valores fixos que só podem ser alterados + antes da compilação + + constantes podem ser de qualquer tipo nativo (integer, real, boolean, + char, string) + +TYPE + vet_char : array [0..255] of CHAR; + // isso declara um novo tipo de variável, vet_char, com 256 caracteres + vet_multd : array of array of INTEGER; + // vetores de vetores são vetores multidimensionais + // use vetores de tamanho 0 (daí, usa-se alocação dinâmica) + // vetores do tipo vet_multd são de duas dimensões + +//declarando variáveis +VAR + int, c, d : INTEGER; + // três variáveis que guardam valores inteiros + // inteiros têm 16 bits (vão de -32768 a 32767) + r : REAL; + // uma variável que guarda um valor real + // reais vão de 3.4E-38 a 3.4E38 + bool : BOOLEAN; + // uma variável que guarda um valor booleano (verdadeiro ou falso) + ch : CHAR; + // uma variável que guarda um caractere + // caracteres têm 8 bits + str : STRING; + // STRING não é um tipo padrão, mas vem na maioria dos compiladores + // string é um vetor de caracteres com tamanho padrão de 255 elementos + s : STRING[50]; + // especificar o tamanho de uma string assim otimiza o uso de memória + my_str: vet_char; + // aqui, uma variável de um tipo personalizado declarado acima + my_2d : vet_multd; + // defina o tamanho de vetores dinâmicos antes de usá-los + +// outros tipos de dados (pascal é uma linguagem fortemente tipada) + + // tipos adicionais de inteiros + b : BYTE; // faixa [0..255] + shi : SHORTINT; // faixa [-128..127] + smi : SMALLINT; // faixa [-32,768..32,767] (inteiro padrão) + w : WORD; // faixa [0..65,535] + li : LONGINT; // faixa [-2,147,483,648..2,147,483,647] + lw : LONGWORD; // faixa [0..4,294,967,295] + c : CARDINAL; // longword + i64 : INT64; // faixa [-9223372036854775808..9223372036854775807] + qw : QWORD; // faixa [0..18,446,744,073,709,551,615] + + // tipos adicionais de reais + rr : REAL; // faixa depende da plataforma (8 bits, 16 bits, etc) + rs : SINGLE; // faixa [1.5E-45..3.4E38] + rd : DOUBLE; // faixa [5.0E-324 .. 1.7E308] + re : EXTENDED; // faixa [1.9E-4932..1.1E4932] + rc : COMP; // faixa [-2E64+1 .. 2E63-1] + +BEGIN + int := 1;// usa-se := para atribuir valores a variáveis + r := 3.14; + ch := 'a'; + str := 'apple'; + bool := true; + //pascal não é case-sensitive (não diferencia maiúsculas de minúsculas) + // uma opção de organização é usar maiúsculas para termos da linguagem + // (BEGIN, END, INTEGER, etc) e constantes + // aritmética + int := 1 + 1; // int deixa de ser 1 e passa a ser 2 + int := int + 1; // int = 2 + 1 = 3; + int := 4 DIV 2; //int = 2 (DIV é uma divisão inteira - ignora o resto) + int := 3 DIV 2; //int = 1 + int := 1 DIV 2; //int = 0 + + bool := true OR false; // bool = true + bool := false AND true; // bool = false + bool := true XOR true; // bool = false + + r := 3 / 2; // usa-se a "/" para divisões entre inteiros + r := int; // um real pode receber um valor inteiro (mas não o contrário) + + c := str[1]; //acessando elementos de um vetor: vetor[índice do elemento] + str := 'hello' + 'world'; //concatenção de strings + + my_str[0] := 'a'; { só se pode atribuir valores a vetores elemento + por elemento (não o vetor inteiro de uma vez) } + + // LAÇOS + WHILE (ch != 'a') DO + BEGIN + writeln('ch é diferente de a'); + IF (ch = 'c') THEN + writeln('ch é igual a c'); + END; + + SETLENGTH(my_2d,10,10); + // inicialização de um vetor com alocação dinâmica; my_2d vira um 10x10 + FOR c := 0 to 9 DO + { vetores começam em 0 e terminam em tamanho-1 + (exceto se, declarando o tipo, forem especificados valores diferentes) } + FOR d := 0 to 9 DO + // a variável usada em um laço FOR deve ter sido declarada no cabeçalho + my_2d[c,d] := c * d; + // acessam-se elementos de vetores multidimensionais com [d1, d2, d3...] + + +END. +``` + +```pascal +PROGRAM programacao_com_funcoes; + +VAR + i, inutil : INTEGER; + +{ OBS: diferença entre procedimento e função + função: realiza operações e retorna valor + procedimento: só realiza operações +} +//declarando e descrevendo uma função +FUNCTION fatorial_recursiva(CONST a: INTEGER) : INTEGER; +{ calcula a! recursivamente } + +// pode-se declarar variáveis locais para funções e procedimentos +// exemplo: +// VAR +// local_a : INTEGER; + +BEGIN + { O bloco ELSE só funciona se não houver ponto e vírgula no bloco do IF + exemplo: + IF a THEN + writeln('a'); + ELSE + writeln('b'); + Isso não permitiria que o programa compilasse } + + IF a >= 1 THEN + // o valor de retorno é atribuído como se a função fosse uma variável + fatorial_recursiva := a * fatorial_recursiva(a-1) + ELSE + fatorial_recursiva := 1; +END; // o END de funções e procedimentos recebe ponto e vírgula + +//declarando e descrevendo um procedimento +PROCEDURE salvainteiro(VAR i : INTEGER; inutil : INTEGER); +{ recebe entrada do usuário e salva na variável i + passagem de valor: + + POR REFERÊNCIA - "VAR i: integer"; implica que alterações na variável i + dentro da função são guardadas para o escopo de todo o programa + + POR VALOR - "inutil: integer"; implica que o valor do argumento é copiado + e alterações na variável inutil não são guardadas +} + +BEGIN + WRITE('Insira um inteiro: '); //escreve sem quebrar linha + READLN(i); //lê i com quebra de linha + inutil := 4; // inutil não terá seu valor alterado fora do procedimento. +END; + +BEGIN // programa principal + inutil := 3; + salvainteiro(i, inutil); + + // escrevendo i! + WRITELN(i, '! = ', factorial_recursion(i)); // escreve e quebra linha + // valores numéricos são automaticamente convertidos para texto na escrita + + // escrever valor de inutil (sempre 3, já que salvainteiro não a altera) + WRITELN('inutil = ', inutil); +END. + +``` + diff --git a/pt-br/python-pt.html.markdown b/pt-br/python-pt.html.markdown index 5afd46d0..82b70117 100644 --- a/pt-br/python-pt.html.markdown +++ b/pt-br/python-pt.html.markdown @@ -464,7 +464,7 @@ Humano.ronca() #=> "*arrrrrrr*" # Você pode importar módulos import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Você pode importar funções específicas de um módulo from math import ceil, floor diff --git a/pt-br/python3-pt.html.markdown b/pt-br/python3-pt.html.markdown index ea0617f4..b72c732a 100644 --- a/pt-br/python3-pt.html.markdown +++ b/pt-br/python3-pt.html.markdown @@ -647,7 +647,7 @@ Human.grunt() # => "*grunt*" # Você pode importar módulos import math -print(math.sqrt(16)) # => 4 +print(math.sqrt(16)) # => 4.0 # Você pode importar apenas funções específicas de um módulo from math import ceil, floor diff --git a/pt-br/stylus-pt.html.markdown b/pt-br/stylus-pt.html.markdown new file mode 100755 index 00000000..804fa806 --- /dev/null +++ b/pt-br/stylus-pt.html.markdown @@ -0,0 +1,228 @@ +--- +language: stylus +filename: learnStylus-pt.styl +contributors: + - ["Salomão Neto", "https://github.com/salomaosnff"] + - ["Isaac Henrique", "https://github.com/Isaachi1"] +lang: pt-br +--- + +Stylus tem como propósito, adicionar funcionalidades às suas folhas de estilos CSS que te ajudam no desenvolvimento, sem que haja a quebra de compartibilidade entre os navegadores Web. +Entre elas estão variáveis, aninhamento, mixins, funções e muito mais. + +A sintaxe do Stylus é muito flexivel podendo utilizar a sintaxe padrão do CSS e deixando opcional o ponto e vírgula (;), dois pontos (:) e até mesmo as chaves ({ e }), tornando assim o seu código ainda mais legível. + +Stylus não fornece novas opções de estilos, mas dá funcionalidades que permitem deixar seu CSS muito mais dinâmico. + + +```scss + +/* Estilo de código +==============================*/ + +/* As chaves, ponto e vírgula, e dois pontos são opcionais no Stylus. */ + +body { + background: #000; +} + +body { + background: #000 +} + +body { + background #000 +} + +body + background #000 + +body + background: #000; + +body + background: #000 + + +// Comentários de linha única são removidos quando Stylus é compilado para CSS. + +/* Comentários multi-line são preservados. */ + + +/* Seletores +==============================*/ + +/* Selecionando elementos dentro de outro elemento */ +body { + background: #000000; + h1 { + color: #FF0000; + } +} + +/* Ou se preferir... */ +body + background #000000 + h1 + color #FF0000 + + +/* Obtendo a referência do elemento pai +==============================*/ +a { + color: #0088dd; + &:hover { + color: #DD8800; + } +} + + +/*Variáveis +==============================*/ + + +/* + É possível armazenar um valor CSS (tais como a cor) de uma variável. + Embora seja opcional, é recomendado adicionar $ antes de um nome de variável + para que você possa distinguir uma variável de outro valor CSS. +*/ + +$primary-color = #A3A4FF +$secondary-color = #51527F +$body-font = 'Roboto', sans-serif + +/* Você pode usar as variáveis em toda a sua folha de estilo. +Agora, se você quer mudar a cor, você só tem que fazer a mudança uma vez. */ + +body + background-color $primary-color + color $secondary-color + font-family $body-font + +/* Quando compilar ficaria assim: */ +body { + background-color: #A3A4FF; + color: #51527F; + font-family: 'Roboto', sans-serif; +} + +/ * +Este é muito mais fácil de manter do que ter de mudar a cor +cada vez que aparece em toda a sua folha de estilo. +* / + + + +/*Mixins +==============================*/ + +/* Se você achar que você está escrevendo o mesmo código para mais de um +elemento, você pode querer armazenar esse código em um mixin. + +center() + display block + margin-left auto + margin-right auto + left 0 + right 0 + +/* Utilizando um mixin */ +body { + center() + background-color: $primary-color +} + +/* Apoś compilar ficaria assim: */ +div { + display: block; + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; + background-color: #A3A4FF; +} + +/* Você pode usar mixins para criar uma propriedade estenográfica. */ + +size($width, $height) + width $width + height $height + +.rectangle + size(100px, 60px) + +.square + size(40px, 40px) + +/* Você pode usar um mixin como uma propriedade CSS. */ +circle($ratio) + width $ratio * 2 + height $ratio * 2 + border-radius $ratio + +.ball + circle 25px + + +/* Interpolação +==============================*/ + +vendor(prop, args) + -webkit-{prop} args + -moz-{prop} args + {prop} args + +border-radius() + vendor('border-radius', arguments) + +box-shadow() + vendor('box-shadow', arguments) + +button + border-radius 1px 2px / 3px 4px + +/* Funções +==============================*/ + +/* Funções no Stylus permitem fazer uma variedade de tarefas, como por exemplo, menipular algum dado. */ + +body { + background darken(#0088DD, 50%) // Escurece a cor #0088DD em 50% +} + +/** Criando sua própria função */ +somar(a, b) + a + b + +body + padding somar(10px, 5) + +/* Condições +==============================*/ +comparar(a, b) + if a > b + maior + else if a < b + menor + else + igual + +comparar(5, 2) // => maior +comparar(1, 5) // => menor +comparar(10, 10) // => igual + +/* Iterações +==============================*/ + +/** +Sintaxe de laço de repetição for: +for <val-name> [, <key-name>] in <expression> +**/ + +for $item in (1..2) /* Repete o bloco 12 vezes */ + .col-{$item} + width ($item / 12) * 100% /* Calcula a largula pelo número da coluna* + +``` + +Agora que você conhece um pouco sobre esse poderoso pré-processador de CSS, você está pronto para criar folhas de estilos mais dinâmicas. Para aprofundar seus conhecimentos visite a documentação oficial do stylus em http://stylus-lang.com. diff --git a/python.html.markdown b/python.html.markdown index df1ca6f2..0cc33a80 100644 --- a/python.html.markdown +++ b/python.html.markdown @@ -328,7 +328,8 @@ filled_dict["four"] = 4 # now, filled_dict["four"] => 4 filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 -# Sets store ... well sets (which are like lists but can contain no duplicates) +# You can declare sets (which are like unordered lists that cannot contain +# duplicate values) using the set object. empty_set = set() # Initialize a "set()" with a bunch of values some_set = set([1, 2, 2, 3, 4]) # some_set is now set([1, 2, 3, 4]) @@ -661,7 +662,7 @@ i.age # => raises an AttributeError # You can import modules import math -print math.sqrt(16) # => 4 +print math.sqrt(16) # => 4.0 # You can get specific functions from a module from math import ceil, floor diff --git a/python3.html.markdown b/python3.html.markdown index c7fbf342..c4f15867 100644 --- a/python3.html.markdown +++ b/python3.html.markdown @@ -41,10 +41,10 @@ Note: This article applies to Python 3 specifically. Check out [here](http://lea 10 * 2 # => 20 35 / 5 # => 7.0 -# Result of integer division truncated down both for positive and negative. +# Integer division rounds down for both positive and negative numbers. 5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too -5 // 3 # => -2 +5.0 // 3.0 # => 1.0 # works on floats too -5.0 // 3.0 # => -2.0 # The result of division is always a float @@ -72,15 +72,24 @@ not False # => True True and False # => False False or True # => True -# Note using Bool operators with ints -# False is 0 and True is 1 +# True and False are actually 1 and 0 but with different keywords +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# Comparison operators look at the numerical value of True and False +0 == False # => True +1 == True # => True +2 == True # => False +-5 != False # => True + +# Using boolean logical operators on ints casts them to booleans for evaluation, but their non-cast value is returned # Don't mix up with bool(ints) and bitwise and/or (&,|) +bool(0) # => False +bool(4) # => True +bool(-6) # => True 0 and 2 # => 0 -5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True --5 != False != True #=> True # Equality is == 1 == 1 # => True @@ -96,7 +105,10 @@ False or True # => True 2 <= 2 # => True 2 >= 2 # => True -# Comparisons can be chained! +# Seeing whether a value is in a range +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# Chaining makes this look nicer 1 < 2 < 3 # => True 2 < 3 < 2 # => False @@ -302,16 +314,19 @@ valid_dict = {(1,2,3):[1,2,3]} # Values can be of any type, however. filled_dict["one"] # => 1 # Get all keys as an iterable with "keys()". We need to wrap the call in list() -# to turn it into a list. We'll talk about those later. Note - Dictionary key -# ordering is not guaranteed. Your results might not match this exactly. -list(filled_dict.keys()) # => ["three", "two", "one"] +# to turn it into a list. We'll talk about those later. Note - for Python +# versions <3.7, dictionary key ordering is not guaranteed. Your results might +# not match the example below exactly. However, as of Python 3.7, dictionary +# items maintain the order at which they are inserted into the dictionary. +list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+ # Get all values as an iterable with "values()". Once again we need to wrap it # in list() to get it out of the iterable. Note - Same as above regarding key # ordering. -list(filled_dict.values()) # => [3, 2, 1] - +list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ # Check for existence of keys in a dictionary with "in" "one" in filled_dict # => True @@ -793,6 +808,7 @@ class Superhero(Human): # add additional class attributes: self.fictional = True self.movie = movie + # be aware of mutable default values, since defaults are shared self.superpowers = superpowers # The "super" function lets you access the parent class's methods diff --git a/racket.html.markdown b/racket.html.markdown index c6b1deba..60a895e0 100644 --- a/racket.html.markdown +++ b/racket.html.markdown @@ -249,7 +249,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (hash-remove m 'a) ; => '#hash((b . 2) (c . 3)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 3. Functions +;; 4. Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Use `lambda' to create functions. @@ -319,7 +319,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' ; => "Hi Finn, 6 extra args" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 4. Equality +;; 5. Equality ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; for numbers use `=' @@ -369,7 +369,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (equal? (list 3) (list 3)) ; => #t ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 5. Control Flow +;; 6. Control Flow ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Conditionals @@ -505,7 +505,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (+ 1 (raise 2))) ; => 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 6. Mutation +;; 7. Mutation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Use `set!' to assign a new value to an existing variable @@ -541,7 +541,7 @@ vec ; => #(1 2 3 4) (hash-remove! m3 'a) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 7. Modules +;; 8. Modules ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Modules let you organize code into multiple files and reusable @@ -568,7 +568,7 @@ vec ; => #(1 2 3 4) ; (show "~a" 1 #\A) ; => error, `show' was not exported ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 8. Classes and Objects +;; 9. Classes and Objects ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Create a class fish% (-% is idiomatic for class bindings) @@ -609,7 +609,7 @@ vec ; => #(1 2 3 4) (send (new (add-color fish%) [size 10] [color 'red]) get-color) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 9. Macros +;; 10. Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Macros let you extend the syntax of the language @@ -651,7 +651,7 @@ vec ; => #(1 2 3 4) ;; it, the compiler will get in an infinite loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 10. Contracts +;; 11. Contracts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Contracts impose constraints on values exported from modules @@ -678,7 +678,7 @@ vec ; => #(1 2 3 4) ;; more details.... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 11. Input & output +;; 12. Input & output ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Racket has this concept of "port", which is very similar to file diff --git a/red.html.markdown b/red.html.markdown index 73baf462..74538bd7 100644 --- a/red.html.markdown +++ b/red.html.markdown @@ -114,12 +114,12 @@ i2 * i1 ; result 2 i1 / i2 ; result 0 (0.5, but truncated towards 0) ; Comparison operators are probably familiar, and unlike in other languages -; you only need a single '=' sign for comparison. +; you only need a single '=' sign for comparison. Inequality is '<>' like in Pascal. ; There is a boolean like type in Red. It has values true and false, but also ; the values on/off or yes/no can be used 3 = 2 ; result false -3 != 2 ; result true +3 <> 2 ; result true 3 > 2 ; result true 3 < 2 ; result false 2 <= 2 ; result true @@ -129,8 +129,8 @@ i1 / i2 ; result 0 (0.5, but truncated towards 0) ; Control Structures ; ; if -; Evaluate a block of code if a given condition is true. IF does not return -; any value, so cannot be used in an expression. +; Evaluate a block of code if a given condition is true. IF returns +; the resulting value of the block or 'none' if the condition was false. if a < 0 [print "a is negative"] ; either @@ -165,7 +165,7 @@ print ["a is " msg lf] ; until ; Loop over a block of code until the condition at end of block, is met. -; UNTIL does not return any value, so it cannot be used in an expression. +; UNTIL always returns the 'true' value from the final evaluation of the last expression. c: 5 until [ prin "o" diff --git a/ro-ro/python-ro.html.markdown b/ro-ro/python-ro.html.markdown index c96e30dc..ada0c034 100644 --- a/ro-ro/python-ro.html.markdown +++ b/ro-ro/python-ro.html.markdown @@ -449,7 +449,7 @@ Om.exclama() #=> "*Aaaaaah*" # Pentru a folosi un modul, trebuie importat import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Putem importa doar anumite funcţii dintr-un modul from math import ceil, floor diff --git a/ru-ru/asymptotic-notation-ru.html.markdown b/ru-ru/asymptotic-notation-ru.html.markdown index 73ad80ba..7fd02c47 100644 --- a/ru-ru/asymptotic-notation-ru.html.markdown +++ b/ru-ru/asymptotic-notation-ru.html.markdown @@ -1,225 +1,225 @@ ---- -category: Algorithms & Data Structures -name: Asymptotic Notation -contributors: - - ["Jake Prather", "http://github.com/JakeHP"] - - ["Divay Prakash", "http://github.com/divayprakash"] -translators: - - ["pru-mike", "http://gihub.com/pru-mike"] -lang: ru-ru ---- - -# О-cимволика - -## Что это такое? - -О-cимволика или асимптотическая запись это система символов позволяющая оценить -время выполнения алгоритма, устанавливая зависимость времени выполнения от -увеличения объема входных данных, так же известна как оценка -сложности алгоритмов. Быстро-ли алгоритм станет невероятно медленным, когда -объем входных данных увеличится? Будет-ли алгоритм выполняться достаточно быстро, -если объем входных данных возрастет? О-символика позволяет ответить на эти -вопросы. - -## Можно-ли по-другому найти ответы на эти вопросы? - -Один способ это подсчитать число элементарных операций в зависимости от -различных объемов входных данных. Хотя это и приемлемое решение, тот объем -работы которого оно потребует, даже для простых алгоритмов, делает его -использование неоправданным. - -Другой способ это измерить какое время алгоритм потребует для завершения на -различных объемах входных данных. В тоже время, точность и относительность -(полученное время будет относиться только к той машине на которой оно -вычислено) этого метода зависит от среды выполнения: компьютерного аппаратного -обеспечения, мощности процессора и т.д. - -## Виды О-символики - -В первом разделе этого документа мы определили, что О-символика -позволяет оценивать алгоритмы в зависимости от изменения размера входных -данных. Представим что алгоритм это функция f, n размер входных данных и -f(n) время выполнения. Тогда для данного алгоритма f c размером входных -данных n получим какое-то результирующее время выполнения f(n). -Из этого можно построить график, где ось Y время выполнения, ось X размер входных -данных и точки на графике это время выполнения для заданного размера входных -данных. - -С помощью О-символики можно оценить функцию или алгоритм -несколькими различными способами. Например можно оценить алгоритм исходя -из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается -анализ на основе верхней оценки. Как правило не используется нижняя оценка, -потому что она не подходит под планируемые условия. Отличный пример алгоритмы -сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка -большинства таких алгоритмов может быть дана как одна операция. В то время как в -большинстве случаев, добавляемые элементы должны быть отсортированы -соответствующим образом при помощи дерева, что может потребовать обхода целой -ветви. Это и есть худший случай, для которого планируется верхняя оценка. - -### Виды функций, пределы и упрощения - -``` -Логарифмическая функция - log n -Линейная функция - an + b -Квадратическая функция - an^2 + bn +c -Полиномиальная функция - an^z + . . . + an^2 + a*n^1 + a*n^0, где z константа -Экспоненциальная функция - a^n, где a константа -``` - -Приведены несколько базовых функций используемых при определении сложности в -различных оценках. Список начинается с самой медленно возрастающей функции -(логарифм, наиболее быстрое время выполнения) и следует до самой быстро -возрастающей функции (экспонента, самое медленное время выполнения). Отметим, -что в то время как 'n' или размер входных данных, возрастает в каждой из этих функций, -результат намного быстрее возрастает в квадратической, полиномиальной -и экспоненциальной по сравнению с логарифмической и линейной. - -Крайне важно понимать, что при использовании описанной далее нотации необходимо -использовать упрощенные выражения. -Это означает, что необходимо отбрасывать константы и слагаемые младших порядков, -потому что если размер входных данных (n в функции f(n) нашего примера) -увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков -и константы становятся пренебрежительно малыми. Таким образом, если есть -константа например размера 2^9001 или любого другого невообразимого размера, -надо понимать, что её упрощение внесёт значительные искажения в точность -оценки. - -Т.к. нам нужны упрощенные выражения, немного скорректируем нашу таблицу... - -``` -Логарифм - log n -Линейная функция - n -Квадратическая функция - n^2 -Полиномиальная функция - n^z, где z константа -Экспонента - a^n, где a константа -``` - -### О-Большое -О-Большое, записывается как **О**, это асимптотическая запись для оценки худшего -случая или для ограничения заданой функции сверху. Это позволяет сделать -_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения -алгоритма. Допустим `f(n)` время выполнения алгоритма и `g(n)` заданная временная -сложность которая проверяется для алгоритма. Тогда `f(n)` это O(g(n)), если -существуют действительные константы с (с > 0) и n<sub>0</sub>, такие -что `f(n)` <= `c g(n)` выполняется для всех n начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>). - -*Пример 1* - -``` -f(n) = 3log n + 100 -g(n) = log n -``` - -Является-ли `f(n)` O(g(n))? -Является-ли `3 log n + 100` O(log n)? -Посмотрим на определение О-Большого: - -``` -3log n + 100 <= c * log n -``` - -Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub> - -``` -3log n + 100 <= 150 * log n, n > 2 (неопределенно для n = 1) -``` - -Да! По определению О-Большого `f(n)` является O(g(n)). - -*Пример 2* - -``` -f(n) = 3 * n^2 -g(n) = n -``` - -Является-ли `f(n)` O(g(n))? -Является-ли `3 * n^2` O(n)? -Посмотрим на определение О-Большого: - -``` -3 * n^2 <= c * n -``` - -Существуют-ли константы c, n<sub>0</sub> такие что выражение верно для всех n > n<sub>0</sub>? -Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)). - -### Омега-Большое -Омега-Большое, записывается как **Ω**, это асимптотическая запись для оценки -лучшего случая или для ограничения заданой функции снизу. Это позволяет сделать -_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения -алгоритма. - -`f(n)` принадлежит Ω(g(n)), если существуют действительные константы -с (с > 0) и <sub>0</sub> (n<sub>0</sub> > 0), такие что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>. - -### Примечание - -Асимптотические оценки сделаные при помощи О-Большое и Омега-Большое могут -как быть так и не быть точными. Для того что бы обозначить что границы не -являются асимптотически точными используются записи о-малое и омега-малое. - -### О-Малое -O-Малое, записывается как **о**, это асимптотическая запись для оценки верхней -границы времени выполнения алгоритма, при условии что граница не является -асимптотически точной. - -`f(n)` является o(g(n)), если можно подобрать такие действительные константы, -что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так -что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>). - -Определения О-символики для О-Большое и О-Малое похожи. Главное отличие в том, -что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется если _**существует**_ -константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется -для _**всех**_ констант с > 0. - -### Омега-малое -Омега-малое, записывается как **ω**, это асимптотическая запись для оценки -верней границы времени выполнения алгоритма, при условии что граница не является -асимптотически точной. - -`f(n)` является ω(g(n)), если можно подобрать такие действительные константы, -что для всех c (c > 0) найдется n<sub>0</sub> (n<sub>0</sub> > 0), так -что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>) - -Определения Ω-символики и ω-символики похожи. Главное отличие в том, что -если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется если _**существует**_ -константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n) -выполняется для _**всех**_ констант с > 0. - -### Тета -Тета, записывается как **Θ**, это асимптотическая запись для оценки -_***асимптотически точной границы***_ времени выполнения алгоритма. - -`f(n)` является Θ(g(n)), если для некоторых действительных -констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0), -`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>). - -∴ `f(n)` является Θ(g(n)) означает что `f(n)` является O(g(n)) -и `f(n)` является Ω(g(n)). - -О-Большое основной инструмент для анализа сложности алгоритмов. -Так же смотрите примеры по ссылкам. - -### Заключение -Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и -посмотреть дополнительную литературу. В них дается более глубокое описание с -определениями и примерами. - - -## Дополнительная литература - -* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/) -* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/) - -## Ссылки - -* [Оценки времени исполнения. Cимвол O()](http://algolist.manual.ru/misc/o_n.php) -* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903) - -## Ссылки (Eng) - -* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1) -* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf) -* [Cheatsheet 2](http://bigocheatsheet.com/) - +---
+category: Algorithms & Data Structures
+name: Asymptotic Notation
+contributors:
+ - ["Jake Prather", "http://github.com/JakeHP"]
+ - ["Divay Prakash", "http://github.com/divayprakash"]
+translators:
+ - ["pru-mike", "http://github.com/pru-mike"]
+lang: ru-ru
+---
+
+# О-символика
+
+## Что это такое?
+
+О-символика, или асимптотическая запись, — это система символов, позволяющая
+оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
+от увеличения объёма входных данных. Она также известна как оценка
+сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
+объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
+если объём входных данных возрастёт? О-символика позволяет ответить на эти
+вопросы.
+
+## Можно ли по-другому найти ответы на эти вопросы?
+
+Один способ — это подсчитать число элементарных операций в зависимости от
+различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
+работы, которого оно потребует, даже для простых алгоритмов делает его
+использование неоправданным.
+
+Другой способ — это измерить, какое время алгоритм потребует для завершения на
+различных объёмах входных данных. В то же время, точность и относительность
+этого метода (полученное время будет относиться только к той машине, на которой
+оно вычислено) зависит от среды выполнения: компьютерного аппаратного
+обеспечения, мощности процессора и т.д.
+
+## Виды О-символики
+
+В первом разделе этого документа мы определили, что О-символика
+позволяет оценивать алгоритмы в зависимости от изменения размера входных
+данных. Представим, что алгоритм — это функция f, n — размер входных данных и
+f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
+данных n получим какое-то результирующее время выполнения f(n).
+Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
+данных, а точки на графике — это время выполнения для заданного размера входных
+данных.
+
+С помощью О-символики можно оценить функцию или алгоритм
+несколькими различными способами. Например, можно оценить алгоритм исходя
+из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
+анализ на основе верхней оценки. Как правило не используется нижняя оценка,
+потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
+сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
+большинства таких алгоритмов может быть дана как одна операция. В то время как в
+большинстве случаев добавляемые элементы должны быть отсортированы
+соответствующим образом при помощи дерева, что может потребовать обхода целой
+ветви. Это и есть худший случай, для которого планируется верхняя оценка.
+
+### Виды функций, пределы и упрощения
+
+```
+Логарифмическая функция — log n
+Линейная функция — an + b
+Квадратичная функция — an^2 + bn +c
+Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
+Показательная функция — a^n, где a — константа
+```
+
+Приведены несколько базовых функций, используемых при определении сложности в
+различных оценках. Список начинается с самой медленно возрастающей функции
+(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
+возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
+что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
+результат намного быстрее возрастает в квадратичной, степенной
+и показательной по сравнению с логарифмической и линейной.
+
+Крайне важно понимать, что при использовании описанной далее нотации необходимо
+использовать упрощённые выражения.
+Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
+потому что если размер входных данных (n в функции f(n) нашего примера)
+увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
+и константы становятся пренебрежительно малыми. Таким образом, если есть
+константа, например, размера 2^9001 или любого другого невообразимого размера,
+надо понимать, что её упрощение внесёт значительные искажения в точность
+оценки.
+
+Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
+
+```
+Логарифм — log n
+Линейная функция — n
+Квадратичная функция — n^2
+Степенная функция — n^z, где z — константа
+Показательная функция — a^n, где a — константа
+```
+
+### О Большое
+О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
+случая, или для ограничения заданной функции сверху. Это позволяет сделать
+_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
+алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
+сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
+существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
+что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
+
+*Пример 1*
+
+```
+f(n) = 3log n + 100
+g(n) = log n
+```
+
+Является ли `f(n)` O(g(n))?
+Является ли `3 log n + 100` O(log n)?
+Посмотрим на определение О Большого:
+
+```
+3log n + 100 <= c * log n
+```
+
+Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
+
+```
+3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
+```
+
+Да! По определению О Большого `f(n)` является O(g(n)).
+
+*Пример 2*
+
+```
+f(n) = 3 * n^2
+g(n) = n
+```
+
+Является ли `f(n)` O(g(n))?
+Является ли `3 * n^2` O(n)?
+Посмотрим на определение О Большого:
+
+```
+3 * n^2 <= c * n
+```
+
+Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
+Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
+
+### Омега Большое
+Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
+лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
+_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
+алгоритма.
+
+`f(n)` является Ω(g(n)), если существуют действительные константы
+c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
+
+### Примечание
+
+Асимптотические оценки, сделаные при помощи О Большого и Омега Большого, могут
+как являться, так и не являться точными. Для того, чтобы обозначить, что границы не
+являются асимптотически точными, используются записи О Малое и Омега Малое.
+
+### О Малое
+O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
+границы времени выполнения алгоритма при условии, что граница не является
+асимптотически точной.
+
+`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
+что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
+что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
+
+Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
+что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
+константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
+для _**всех**_ констант c > 0.
+
+### Омега Малое
+Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
+верхней границы времени выполнения алгоритма при условии, что граница не является
+асимптотически точной.
+
+`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
+что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
+что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
+
+Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
+если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
+константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
+выполняется для _**всех**_ констант c > 0.
+
+### Тета
+Тета, записывается как **Θ**, — это асимптотическая запись для оценки
+_***асимптотически точной границы***_ времени выполнения алгоритма.
+
+`f(n)` является Θ(g(n)), если для некоторых действительных
+констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
+`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
+
+∴ `f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n))
+и `f(n)` является Ω(g(n)).
+
+О Большое — основной инструмент для анализа сложности алгоритмов.
+Также см. примеры по ссылкам.
+
+### Заключение
+Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
+посмотреть дополнительную литературу. В ней даётся более глубокое описание с
+определениями и примерами.
+
+
+## Дополнительная литература
+
+* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
+* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
+
+## Ссылки
+
+* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
+* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
+
+## Ссылки (англ.)
+
+* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
+* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
+* [Cheatsheet 2](http://bigocheatsheet.com/)
+
diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown index 5e99afc2..ce918340 100644 --- a/ru-ru/bash-ru.html.markdown +++ b/ru-ru/bash-ru.html.markdown @@ -11,29 +11,40 @@ contributors: - ["Rahil Momin", "https://github.com/iamrahil"] - ["Gregrory Kielian", "https://github.com/gskielian"] - ["Etan Reisner", "https://github.com/deryni"] + - ["Jonathan Wang", "https://github.com/Jonathansw"] + - ["Leo Rudberg", "https://github.com/LOZORD"] + - ["Betsy Lorton", "https://github.com/schbetsy"] + - ["John Detter", "https://github.com/jdetter"] + - ["Harry Mumford-Turner", "https://github.com/harrymt"] + - ["Martin Nicholson", "https://github.com/mn113"] translators: - ["Andrey Samsonov", "https://github.com/kryzhovnik"] - - ["Andre Polykanine", "https://github.com/Oire"] + - ["Andre Polykanine", "https://github.com/Menelion"] filename: LearnBash-ru.sh lang: ru-ru --- -Bash - это командная оболочка unix (unix shell), которая распространялась как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию для Linux и Mac OS X. -Почти все нижеприведенные примеры могут быть частью shell-скриптов или исполнены напрямую в shell. +Bash — это командная оболочка unix, которая распространялась как оболочка +для операционной системы GNU и используется в качестве оболочки по умолчанию +для Linux и Mac OS X. +Почти все нижеприведённые примеры могут быть частью shell-скриптов +или исполнены напрямую в shell. [Подробнее.](http://www.gnu.org/software/bash/manual/bashref.html) ```bash #!/bin/bash -# Первая строка скрипта - это shebang, который сообщает системе, как исполнять -# этот скрипт: http://en.wikipedia.org/wiki/Shebang_(Unix) -# Как вы уже поняли, комментарии начинаются с #. Shebang - тоже комментарий. +# Первая строка скрипта — это шебанг, который сообщает системе, как исполнять +# этот скрипт: https://ru.wikipedia.org/wiki/Шебанг_(Unix) +# Как вы уже поняли, комментарии начинаются с «#». Шебанг — тоже комментарий. # Простой пример hello world: echo Hello world! # Отдельные команды начинаются с новой строки или разделяются точкой с запятой: echo 'Это первая строка'; echo 'Это вторая строка' +# => Это первая строка +# => Это вторая строка # Вот так объявляется переменная: VARIABLE="Просто строка" @@ -41,103 +52,234 @@ VARIABLE="Просто строка" # но не так: VARIABLE = "Просто строка" # Bash решит, что VARIABLE - это команда, которую он должен исполнить, -# и выдаст ошибку, потому что не сможет найти ее. +# и выдаст ошибку, потому что не сможет найти её. # и не так: VARIABLE= 'Просто строка' -# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить, -# и выдаст ошибку, потому что не сможет найти такой команды +# Тут Bash решит, что 'Просто строка' — это команда, которую он должен +# исполнить, и выдаст ошибку, потому что не сможет найти такой команды # (здесь 'VARIABLE=' выглядит как присвоение значения переменной, # но только в контексте исполнения команды 'Просто строка'). # Использование переменой: -echo $VARIABLE -echo "$VARIABLE" -echo '$VARIABLE' -# Когда вы используете переменную - присваиваете, экспортируете и т.д. - +echo $VARIABLE # => Просто строка +echo "$VARIABLE" # => Просто строка +echo '$VARIABLE' # => $Variable +# Когда вы используете переменную — присваиваете, экспортируете и т.д. — # пишите её имя без $. А для получения значения переменной используйте $. # Заметьте, что ' (одинарные кавычки) не раскрывают переменные в них. -# Подстановка строк в переменные -echo ${VARIABLE/Просто/A} -# Это выражение заменит первую встреченную подстроку "Просто" на "A" +# Раскрытие параметров ${ }: +echo ${Variable} # => Просто строка +# Это простое использование раскрытия параметров +# Раскрытие параметров получает значение переменной. +# Оно «раскрывает», или печатает это значение. +# ̶Значение можно изменить во время раскрытия. +# Ниже приведены другие модификации при раскрытии параметров. + +# Замена подстрок в переменных +echo ${Variable/Просто/Это} # => Это строка +# Заменит первое вхождение «Просто» на «Это» # Взять подстроку из переменной LENGTH=7 -echo ${VARIABLE:0:LENGTH} -# Это выражение вернет только первые 7 символов переменной VARIABLE +echo ${VARIABLE:0:LENGTH} # => Просто +# Это выражение вернёт только первые 7 символов переменной VARIABLE +echo ${Variable: -5} # => трока +# Вернёт последние 5 символов (обратите внимание на пробел перед «-5») + +# Длина строки +echo ${#Variable} # => 13 -# Значение по умолчанию -echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"} +# Значение переменной по умолчанию +echo ${FOO:-"ЗначениеПоУмолчаниюЕслиFooПустаИлиНеНайдена"} +# => ЗначениеПоУмолчаниюЕслиFooПустаИлиНеНайдена # Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO=""); -# ноль (FOO=0) вернет 0. -# Заметьте, что в любом случае значение самой переменной FOO не изменится. +# ноль (FOO=0) вернёт 0. +# Заметьте, что в любом случае это лишь вернёт значение по умолчанию, +# а значение самой переменной FOO не изменится. + +# Объявить массив из 6 элементов +array0=(один два три четыре пять шесть) +# Вывести первый элемент +echo $array0 # => "один" +# Вывести первый элемент +echo ${array0[0]} # => "один" +# Вывести все элементы +echo ${array0[@]} # => "один два три четыре пять шесть" +# Вывести число элементов +echo ${#array0[@]} # => "6" +# Вывести число символов в третьем элементе +echo ${#array0[2]} # => "3" +# Вывести 2 элемента, начиная с четвёртого +echo ${array0[@]:3:2} # => "четыре пять" +# Вывести все элементы, каждый на своей строке +for i in "${array0[@]}"; do + echo "$i" +done + +# Раскрытие скобок { } +# Используется для создания произвольных строк +echo {1..10} # => 1 2 3 4 5 6 7 8 9 10 +echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z +# Выведет диапазон от начального до конечного значения # Встроенные переменные: # В bash есть полезные встроенные переменные, например -echo "Последнее возвращенное значение: $?" -echo "PID скрипта: $$" -echo "Количество аргументов: $#" -echo "Аргументы скрипта: $@" +echo "Значение, возвращённое последней программой: $?" +echo "Идентификатор процесса скрипта: $$" +echo "Число аргументов, переданных скрипту: $#" +echo "Все аргументы, переданные скрипту: $@" echo "Аргументы скрипта, распределённые по отдельным переменным: $1 $2..." -# Чтение аргументов из устройста ввода: +# Теперь, когда мы знаем, как выводить и использовать переменные, +# давайте изучим некоторые другие основы Bash! + +# Текущая директория доступна по команде `pwd`. +# `pwd` расшифровывается как «print working directory», т.е. +# «напечатать рабочую директорию». +# Мы также можем использовать встроенную переменную `$PWD`. +# Заметьте, следующие выражения эквивалентны: +echo "Я в $(pwd)" # выполняет `pwd` и раскрывает вывод +echo "Я в $PWD" # раскрывает переменную + +# Если вы получаете слишком много информации в терминале или из скрипта, +# команда `clear` очистит экран +clear +# Очистить экран можно также с помощью Ctrl+L + +# Чтение аргументов с устройства ввода: echo "Как Вас зовут?" read NAME # Обратите внимание, что нам не нужно определять новую переменную echo Привет, $NAME! # У нас есть обычная структура if: # наберите 'man test' для получения подробной информации о форматах условия -if [ $NAME -ne $USER ] +if [ $NAME != $USER ] then echo "Имя не совпадает с именем пользователя" else echo "Имя совпадает с именем пользователя" fi +# Истинно, если значение $Name не совпадает с текущим именем пользователя -# Примечание: если $Name пустой, bash интерпретирует код как: -if [ -ne $USER ] +# Примечание: если $Name пуста, bash интерпретирует код так: +if [ != $USER ] # а это ошибочная команда -# поэтому такие переменные нужно использовать так: -if [ "$Name" -ne $USER ] ... -# когда $Name пустой, bash видит код как: -if [ "" -ne $USER ] ... +# поэтому «безопасный» способ использовать пустые переменные в Bash таков: +if [ "$Name" != $USER ] ... +# при этом, когда $Name пуста, bash видит код так: +if [ "" != $USER ] ... # что работает правильно # Также есть условное исполнение echo "Исполнится всегда" || echo "Исполнится, если первая команда завершится ошибкой" +# => Исполнится всегда echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно" +# => Исполнится всегда +# => Исполнится, если первая команда выполнится удачно -# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок: -if [ $NAME == "Steve" ] && [ $AGE -eq 15 ] + +# Чтобы использовать && и || в выражениях if, нужно несколько пар скобок: +if [ $NAME == "Стив" ] && [ $AGE -eq 15 ] +then + echo "Исполнится, если $NAME равно Стив И $AGE равно 15." +fi + +if [ $NAME == "Дания" ] || [ $NAME == "Зак" ] then - echo "Исполнится, если $NAME равно Steve И $AGE равно 15." + echo "Исполнится, если $NAME равно Дания ИЛИ Зак." fi -if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ] +# Есть ещё оператор «=~», который проверяет строку +# на соответствие регулярному выражению: +Email=me@example.com +if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]] then - echo "Исполнится, если $NAME равно Daniya ИЛИ Zach." + echo "адрес корректный!" fi +# Обратите внимание, что =~ работает только внутри +# двойных квадратных скобок [[ ]], +# которые несколько отличаются от одинарных скобок [ ]. +# Для более подробной информации см. http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs. + +# Переопределить команду «ping» как псевдоним для отправки только пяти пакетов +alias ping='ping -c 5' +# Экранировать псевдоним и использовать команду под своим именем вместо него +\ping 192.168.1.1 +# Вывести все псевдонимы +alias -p # Выражения обозначаются таким форматом: -echo $(( 10 + 5 )) +echo $(( 10 + 5 )) # => 15 -# В отличие от других языков программирования, Bash - это командная оболочка, +# В отличие от других языков программирования, Bash — это командная оболочка, # а значит, работает в контексте текущей директории. # Вы можете просматривать файлы и директории в текущей директории командой ls: -ls +ls # перечисляет файлы и поддиректории в текущей директории -# У этой команды есть опции: +# У этой команды есть параметры: ls -l # Показать каждый файл и директорию на отдельной строке +ls -t # сортирует содержимое по дате последнего изменения (в обратном порядке) +ls -R # Рекурсивно выполняет `ls` по данной директории и всем её поддиректориям # Результат предыдущей команды может быть направлен на вход следующей. # Команда grep фильтрует ввод по шаблону. -# Так мы можем просмотреть только *.txt файлы в текущей директории: +# Так мы можем просмотреть только *.txt-файлы в текущей директории: ls -l | grep "\.txt" +# Для вывода файлов в стандартный поток используйте `cat`: +cat file.txt + +# С помощью `cat` мы также можем читать файлы: +Contents=$(cat file.txt) +echo "НАЧАЛО ФАЙЛА\n$Contents\nКОНЕЦ ФАЙЛА" # «\n» выводит символ перевода на новую строку +# => НАЧАЛО ФАЙЛА +# => [Содержимое file.txt] +# => КОНЕЦ ФАЙЛА + +# Для копирования файлов и директорий из одного места в другое используйте `cp`. +# `cp` создаёт новые версии исходных элементов, +# так что редактирование копии не повлияет на оригинал (и наоборот). +# Обратите внимание, что команда перезапишет целевой элемент, если он уже существует. +cp srcFile.txt clone.txt +cp -r srcDirectory/ dst/ # рекурсивное копирование + +# Если вам нужно обмениваться файлами между компьютерами, посмотрите в сторону `scp` или `sftp`. +# `scp` ведёт себя очень похоже на `cp`. +# `sftp` более интерактивна. + +# Для перемещения файлов и директорий из одного места в другое используйте `mv`. +# Команда `mv` похожа на `cp`, но она удаляет исходный элемент. +# `mv` также можно использовать для переименования файлов! +mv s0urc3.txt dst.txt # Извините, тут были Leet-хакеры... + +# Поскольку Bash работает в контексте текущей директории, вам может понадобиться +# запустить команду в другой директории. +# Для изменения местоположения у нас есть `cd`: +cd ~ # Перейти в домашнюю директорию +cd # Также переходит в домашнюю директорию +cd .. # Перейти на уровень вверх + # (например, из /home/username/Downloads в /home/username) +cd /home/username/Documents # перейти в указанную директорию +cd ~/Documents/.. # Всё ещё в домашней директории. Так ведь?? +cd - # Перейти в последнюю директорию +# => /home/username/Documents + +# Для работы по директориям используйте субоболочки +(echo "Сначала я здесь: $PWD") && (cd someDir; echo "А теперь я тут: $PWD") +pwd # всё ещё в первой директории + +# Для создания новых директорий используйте `mkdir`. +mkdir myNewDir +# Флаг `-p` указывает, что нужно создать все промежуточные директории, если нужно. +mkdir -p myNewDir/with/intermediate/directories +# Если промежуточные директории до этого не существовали, +# вышеприведённая команда без флага `-p` вернёт ошибку + # Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr). -# Следующая команда означает: читать из stdin, пока не встретится ^EOF$, и -# перезаписать hello.py следующим строками (до строки "EOF"): +# Прочитать из stdin, пока не встретится ^EOF$, и +# перезаписать hello.py следующими строками (до строки "EOF"): cat > hello.py << EOF #!/usr/bin/env python from __future__ import print_function @@ -147,23 +289,25 @@ print("#stderr", file=sys.stderr) for line in sys.stdin: print(line, file=sys.stdout) EOF +# Если первый «EOF» не заключён в кавычки, переменные будут раскрыты # Запуск hello.py с разными вариантами перенаправления потоков # стандартных ввода, вывода и ошибок: -python hello.py < "input.in" -python hello.py > "output.out" -python hello.py 2> "error.err" -python hello.py > "output-and-error.log" 2>&1 -python hello.py > /dev/null 2>&1 +python hello.py < "input.in" # передать input.in в качестве ввода в скрипт +python hello.py > "output.out" # передать вывод скрипта в output.out +python hello.py 2> "error.err" # передать вывод ошибок в error.err +python hello.py > "output-and-error.log" 2>&1 # передать вывод скрипта и ошибок в output-and-error.log +python hello.py > /dev/null 2>&1 # передать вывод скрипта и ошибок в «чёрную дыру» /dev/null, т.е., без вывода # Поток ошибок перезапишет файл, если этот файл существует, -# поэтому, если вы хотите дописывать файл, используйте ">>": +# поэтому, если вы хотите дописывать файл, используйте «>>»: python hello.py >> "output.out" 2>> "error.err" -# Переписать output.txt, дописать error.err и сосчитать строки: +# Перезаписать output.txt, дописать error.err и сосчитать строки: info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err wc -l output.out error.err -# Запустить команду и вывести ее файловый дескриптор (смотрите: man fd) +# Запустить команду и вывести её файловый дескриптор (например, /dev/fd/123) +# См. man fd echo <(echo "#helloworld") # Перезаписать output.txt строкой "#helloworld": @@ -172,40 +316,49 @@ echo "#helloworld" > output.out echo "#helloworld" | cat > output.out echo "#helloworld" | tee output.out >/dev/null -# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим) +# Подчистить временные файлы с подробным выводом ('-i' — интерактивный режим) +# ВНИМАНИЕ: команду `rm` отменить нельзя rm -v output.out error.err output-and-error.log +rm -r tempDir/ # рекурсивное удаление # Команды могут быть подставлены в строку с помощью $( ): # следующие команды выводят число файлов и директорий в текущей директории. echo "Здесь $(ls | wc -l) элементов." -# То же самое можно сделать с использованием обратных кавычек, +# То же самое можно сделать с использованием обратных кавычек «``», # но они не могут быть вложенными, поэтому предпочтительно использовать $( ). echo "Здесь `ls | wc -l` элементов." # В Bash есть структура case, которая похожа на switch в Java и C++: case "$VARIABLE" in - # Перечислите шаблоны для условий, которые хотите отловить + # Перечислите шаблоны для условий, которые хотите выполнить 0) echo "Тут ноль.";; 1) echo "Тут один.";; *) echo "Это не пустое значение.";; esac -# Цикл for перебирает элементы переданные в аргументе: +# Цикл for перебирает элементы по количеству аргументов: # Содержимое $VARIABLE будет напечатано три раза. for VARIABLE in {1..3} do echo "$VARIABLE" done +# => 1 +# => 2 +# => 3 + -# Или с использованием "традиционного" синтаксиса цикла for: +# Или с использованием «традиционного» синтаксиса цикла for: for ((a=1; a <= 3; a++)) do echo $a done +# => 1 +# => 2 +# => 3 # Цикл for можно использовать для действий с файлами. -# Запустим команду 'cat' для файлов file1 и file2 +# Запустим команду «cat» для файлов file1 и file2 for VARIABLE in file1 file2 do cat "$VARIABLE" @@ -221,52 +374,89 @@ done # Цикл while: while [ true ] do - echo "тело цикла здесь..." + echo "Здесь тело цикла..." break done +# => Здесь тело цикла... -# Вы можете определять функции +# Вы также можете определять функции # Определение: function foo () { - echo "Аргументы работают также, как аргументы скрипта: $@" - echo "и: $1 $2..." + echo "Аргументы работают так же, как и аргументы скрипта: $@" + echo "И так: $1 $2..." echo "Это функция" return 0 } +# Вызовем функцию `foo` с двумя аргументами, arg1 и arg2: +foo arg1 arg2 +# => Аргументы работают так же, как и аргументы скрипта: arg1 arg2 +# => И так: arg1 arg2... +# => Это функция # или просто bar () { - echo "Другой способ определить функцию!" + echo "Другой способ определять функции!" return 0 } +# Вызовем функцию `bar` без аргументов: +bar # => Другой способ определять функции! # Вызов функции -foo "Мое имя" $NAME +foo "Меня зовут" $NAME # Есть много полезных команд, которые нужно знать: # напечатать последние 10 строк файла file.txt tail -n 10 file.txt + # напечатать первые 10 строк файла file.txt head -n 10 file.txt + # отсортировать строки file.txt sort file.txt -# отобрать или наоборот пропустить повторяющиеся строки (с опцией -d отбирает) + +# отобрать или наоборот пропустить повторяющиеся строки (с параметром `-d` отбирает строки) uniq -d file.txt -# напечатать только первую колонку перед символом ',' + +# напечатать только первый столбец перед символом «,» cut -d ',' -f 1 file.txt -# заменить каждое 'okay' на 'great' в файле file.txt (regex поддерживается) -sed -i 's/okay/great/g' file.txt -# вывести в stdout все строки из file.txt, совпадающие с шаблоном regex; -# этот пример выводит строки, которые начинаются на "foo" и оканчиваются "bar" + +# заменить каждое вхождение «хорошо» на «прекрасно» в файле file.txt +# (поддерживаются регулярные выражения) +sed -i 's/хорошо/прекрасно/g' file.txt + +# вывести в stdout все строки из file.txt, соответствующие регулярному выражению +# этот пример выводит строки, которые начинаются на «foo» и оканчиваются на «bar» grep "^foo.*bar$" file.txt -# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон + +# Передайте параметр `-c`, чтобы вывести лишь число строк, +# соответствующих регулярному выражению grep -c "^foo.*bar$" file.txt -# чтобы искать по строке, а не шаблону regex, используйте fgrep (или grep -F) + +# Ниже приведены другие полезные параметры: +grep -r "^foo.*bar$" someDir/ # рекурсивный `grep` +grep -n "^foo.*bar$" file.txt # задаются номера строк +grep -rI "^foo.*bar$" someDir/ # рекурсивный `grep` с игнорированием двоичных файлов + +# Выполнить тот же изначальный поиск, но удалив строки, содержащие «baz» +grep "^foo.*bar$" file.txt | grep -v "baz" + +# чтобы искать непосредственно по строке, а не в соответствии +# с регулярным выражением, используйте fgrep (или grep -F): fgrep "^foo.*bar$" file.txt -# Читайте встроенную документацию оболочки Bash командой 'help': +# Команда `trap` позволяет выполнить некую команду, когда ваш скрипт +# принимает определённый Posix-сигнал. В следующем примере `trap` выполнит `rm`, +# если скрипт примет один из трёх перечисленных сигналов. +trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM + +# `sudo` используется для выполнения команд с правами суперпользователя +NAME1=$(whoami) +NAME2=$(sudo whoami) +echo "Был $NAME1, затем стал более мощным $NAME2" + +# Читайте встроенную документацию оболочки Bash командой `help`: help help help help for @@ -274,18 +464,18 @@ help return help source help . -# Читайте Bash man-документацию +# Читайте man-документацию Bash командой `man`: apropos bash man 1 bash man bash -# Читайте документацию info (? для помощи) +# Читайте документацию info (? для справки) apropos info | grep '^info.*(' man info info info info 5 info -# Читайте bash info документацию: +# Читайте info-документацию Bash: info bash info bash 'Bash Features' info bash 6 diff --git a/ru-ru/php-composer-ru.html.markdown b/ru-ru/php-composer-ru.html.markdown index ef6e4912..4bdf1029 100644 --- a/ru-ru/php-composer-ru.html.markdown +++ b/ru-ru/php-composer-ru.html.markdown @@ -2,24 +2,26 @@ category: tool tool: composer contributors: - - ["Alesey Lysenko", "https://github.com/nasgul"] + - ["Brett Taylor", "https://github.com/glutnix"] +translators: + - ["Aleksey Lysenko", "https://github.com/nasgul"] filename: LearnComposer-ru.sh lang: ru-ru --- -[Composer](https://getcomposer.org/) это инструмент управления зависимостями в PHP. +[Composer](https://getcomposer.org/) — это инструмент управления зависимостями в PHP. Он позволяет вам декларировать библиотеки, от которых зависит ваш проект, -и он будет управлять (устанавливать / обновлять) их для вас. +и он будет управлять ими, то есть устанавливать/обновлять их для вас. # Установка ```sh # Устанавливаем composer.phar в текущую папку curl -sS https://getcomposer.org/installer | php -# Если вы используете этот подход, вам нужно будет вызвать композер следующим образом: +# Если вы используете этот подход, вам нужно будет вызвать Composer следующим образом: php composer.phar about -# Устанавливаем с бинарников ~/bin/composer +# Устанавливаем бинарный файл в ~/bin/composer # Примечание: убедитесь, что ~/bin находится в переменной PATH вашего окружения curl -sS https://getcomposer.org/installer | php -- --install-dir=~/bin --filename=composer ``` @@ -30,58 +32,59 @@ curl -sS https://getcomposer.org/installer | php -- --install-dir=~/bin --filena ## Подтверждение установки ```sh -# # Проверить версию и параметры списка +# # Проверить версию и перечислить параметры composer # Получить дополнительную помощь для параметров composer help require -# Проверьте, способен ли Composer делать то, что ему нужно, и если он обновлен -композитор диагностирует +# Проверить, способен ли Composer делать то, что ему нужно, и обновлён ли он composer diagnose -composer diag # shorthand +composer diag # краткий вариант -# Обновление Composer к последней версии +# Обновление Composer до последней версии composer self-update -composer self # shorthand +composer self # краткий вариант ``` # Использование -Композитор сохраняет ваши зависимости проекта в `composer.json`. -Вы можете отредактировать этот файл, но лучше всего позволить Composer управлять им для вас. +Composer сохраняет ваши зависимости проекта в `composer.json`. +Вы можете отредактировать этот файл, но лучше всего позволить Composer управлять им за вас. ```sh # Создать новый проект в текущей папке composer init # запускается интерактивная анкета с просьбой предоставить подробную информацию о вашем проекте. -# Оставляя их пустым, все прекрасно, если вы не делаете другие проекты зависимыми от этого. +# Вы прекрасно можете оставить ответы пустыми, если не делаете другие проекты +# зависимыми от создаваемого проекта. # Если файл composer.json уже существует, загрузите зависимости composer install -# Чтобы загрузить только производственные зависимости, т. Е. Исключая зависимости разработки +# Чтобы загрузить только зависимости для готового продукта, т.е. +# исключая зависимости для разработки composer install --no-dev -# Добавить зависимость от этого проекта +# Добавить зависимость для готового продукта к этому проекту composer require guzzlehttp/guzzle -# выяснит, какая последняя версия guzzlehttp / guzzle есть, -# загрузите ее и добавьте новую зависимость в поле require.console. +# выяснит, какая существует последняя версия guzzlehttp / guzzle, +# загрузит её и добавит новую зависимость в поле require файла composer.json. composer require guzzlehttp/guzzle:6.0.* -# будет загружать последнюю версию, соответствующую шаблону (например, 6.0.2), -# и добавить зависимость к полю require.json +# Загрузит последнюю версию, соответствующую шаблону (например, 6.0.2), +# и добавит зависимость к полю require файла composer.json composer require --dev phpunit/phpunit:~4.5.0 -# потребуется как зависимость от разработки. +# Добавит как зависимость для разработки. # Будет использовать последнюю версию> = 4.5.0 и <4.6.0 composer require-dev phpunit/phpunit:^4.5.0 -# потребуется как зависимость от разработки. Будет использовать последнюю версию> = 4.5.0 и <5.0 +# Добавит как зависимость для разработки. +# Будет использовать последнюю версию> = 4.5.0 и <5.0 # Для получения дополнительной информации о совместимости версий Composer см. -# [Документация композитора по версиям] (https://getcomposer.org/doc/articles/versions.md) -# для получения более подробной информации +# [Документацию Composer по версиям] (https://getcomposer.org/doc/articles/versions.md) # Чтобы узнать, какие пакеты доступны для установки и в настоящее время установлены composer show @@ -89,36 +92,37 @@ composer show # Чтобы узнать, какие пакеты в настоящее время установлены composer show --installed -# Чтобы найти пакет с «mailgun» в его названии или описании +# Чтобы найти пакет со строкой «mailgun» в названии или описании composer search mailgun ``` [Packagist.org](https://packagist.org/) является основным хранилищем для пакетов Composer. -Поиск там для существующих сторонних пакетов. +Существующие сторонние пакеты ищите там. -## `composer.json` vs `composer.lock` +## composer.json` и `composer.lock` -Файл `composer.json` хранит ваши параметры плавающей версии вашего проекта для каждой зависимости, -а также другую информацию. +Файл `composer.json` хранит параметры допустимых версий каждой зависимости +вашего проекта, а также другую информацию. -Файл `composer.lock` хранит точно, какую версию он загрузил для каждой зависимости. +Файл `composer.lock` хранит точную загруженную версию каждой зависимости. Никогда не редактируйте этот файл. -Если вы включите файл `composer.lock` в свой репозиторий git, -каждый разработчик установит текущую версию зависимостей. -Даже когда выпущена новая версия зависимости, Composer продолжит загрузку версии, -записанной в файле блокировки. +Если вы включите файл `composer.lock` в свой Git-репозиторий, +каждый разработчик установит версии зависимостей, которые вы используете. +Даже когда будет выпущена новая версия зависимости, Composer продолжит загрузку версии, +записанной в lock-файле. ```sh -# Если вы хотите обновить все зависимости до их новейшей версии, -# которые по-прежнему соответствуют вашим предпочтениям в версии обновление композитора +# Если вы хотите обновить все зависимости до новейших версий, +# которые по-прежнему соответствуют вашим предпочтениям для версий composer update -# Если вам нужна новая версия определенной зависимости: +# Если вам нужна новая версия определённой зависимости: composer update phpunit/phpunit -# Если вы хотите перенести пакет на более новую версию, +# Если вы хотите перенести пакет на более новую версию +#с изменением предпочитаемой версии, # вам может потребоваться сначала удалить старый пакет и его зависимости. composer remove --dev phpunit/phpunit composer require --dev phpunit/phpunit:^5.0 @@ -126,8 +130,8 @@ composer require --dev phpunit/phpunit:^5.0 ## Автозагрузчик -Composer создает класс автозагрузки, который вы можете потребовать от своего приложения. -Вы можете создавать экземпляры классов через их пространство имен. +Composer создаёт класс автозагрузки, который вы можете вызвать +из своего приложения. Вы можете создавать экземпляры классов через пространство имён. ```php require __DIR__ . '/vendor/autoload.php'; @@ -135,15 +139,12 @@ require __DIR__ . '/vendor/autoload.php'; $mailgun = new Mailgun\Mailgun("key"); ``` -### PSR-4 Autoloader +### PSR-4-совместимый автозагрузчик -### Автозагрузчик PSR-4 -Вы можете добавить свои собственные пространства имен в автозагрузчик. +Вы можете добавить в автозагрузчик свои собственные пространства имён. -Вы можете добавить свои собственные пространства имен в автозагрузчик. - -В `composer.json` добавьте поле 'autoload': +Добавьте поле `autoload` в `composer.json`: ```json { @@ -152,31 +153,31 @@ $mailgun = new Mailgun\Mailgun("key"); } } ``` -Это скажет автозагрузчику искать что-либо в пространстве имен `\ Acme \` в папке `src`. +Это скажет автозагрузчику искать что-либо в пространстве имён `\Acme` в папке `src`. Вы также можете использовать -[PSR-0, Classmap или просто список файлов для включения](https://getcomposer.org/doc/04-schema.md#autoload). -Также существует поле `autoload-dev` для пространств имен, предназначенных только для разработки. +[PSR-0, карту классов или просто список файлов для включения](https://getcomposer.org/doc/04-schema.md#autoload). +Также существует поле `autoload-dev` для пространств имён, предназначенных только для разработки. При добавлении или изменении ключа автозагрузки вам необходимо перестроить автозагрузчик: ```sh composer dump-autoload -composer dump # shorthand +composer dump # краткий вариант -# Оптимизирует пакеты PSR0 и PSR4 для загрузки классов. -# Медленно запускается, но улучшает производительность при производстве. +# Оптимизирует пакеты PSR0 и PSR4 для загрузки классов с помощью карты классов. +# Медленно запускается, но улучшает производительность готового продукта. composer dump-autoload --optimize --no-dev ``` -# Composer Кэш +# Кэш Composer ```sh -# Composer сохранит загруженные пакеты для использования в будущем. Очистите его с помощью: +# Composer хранит загруженные пакеты для использования в будущем. Очистите кэш с помощью: composer clear-cache ``` -# Поиск проблемы +# Устранение неполадок ```sh composer diagnose @@ -184,13 +185,13 @@ composer self-update composer clear-cache ``` -## Темы, которые пока (пока) не включены в этот учебник +## Темы, которые ещё (пока) не включены в этот учебник -* Создание и распространение ваших собственных пакетов на Packagist.org или в другом месте +* Создание и распространение ваших собственных пакетов на Packagist.org или в другом репозитории * Предварительные и пост-скриптовые перехватчики: запуск задач, -когда происходят определенные события композитора +когда происходят определенные события Composer -### Рекомендации +### Ссылки * [Composer - Dependency Manager for PHP](https://getcomposer.org/) * [Packagist.org](https://packagist.org/) diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown index 43142eff..6087a686 100644 --- a/ru-ru/python-ru.html.markdown +++ b/ru-ru/python-ru.html.markdown @@ -541,7 +541,7 @@ Human.grunt() #=> "*grunt*" # Вы можете импортировать модули import math -print(math.sqrt(16)) #=> 4 +print(math.sqrt(16)) #=> 4.0 # Вы можете импортировать отдельные функции модуля from math import ceil, floor diff --git a/ru-ru/yaml-ru.html.markdown b/ru-ru/yaml-ru.html.markdown new file mode 100644 index 00000000..6eb580d9 --- /dev/null +++ b/ru-ru/yaml-ru.html.markdown @@ -0,0 +1,189 @@ +--- +language: yaml +filename: learnyaml-ru.yaml +contributors: +- [Adam Brenecki, 'https://github.com/adambrenecki'] +- [Suhas SG, 'https://github.com/jargnar'] +translators: +- [Sergei Babin, 'https://github.com/serzn1'] +lang: ru-ru +--- + +YAML как язык сериализации данных предназначен прежде всего для использования людьми. + +Это строгое надмножество JSON с добавлением синтаксически значимых переносов строк и +отступов как в Python. Тем не менее, в отличие от Python, YAML запрещает +использование табов для отступов. + +```yaml +--- # начало документа + +# Комментарий в YAML выглядит как-то так. + +###################### +# Скалярные величины # +###################### + +# Наш корневой объект (который продолжается для всего документа) будет соответствовать +# типу map, который в свою очередь соответствует словарю, хешу или объекту в других языках. +key: value +another_key: Другое значение ключа. +a_number_value: 100 +scientific_notation: 1e+12 +# Число 1 будет интерпретировано как число, а не как логический тип. Если необходимо чтобы +# значение было интерпретировано как логическое, необходимо использовать true +boolean: true +null_value: null +key with spaces: value + +# Обратите внимание что строки используются без кавычек, но могут и с кавычками. +however: 'Строка заключенная в кавычки.' +'Ключ заключенный в кавычки.': "Полезно если нужно использовать ':' в вашем ключе." +single quotes: 'Содержит ''одну'' экранированную строку' +double quotes: "Содержит несколько: \", \0, \t, \u263A, \x0d\x0a == \r\n, экранированных строк." + +# Многострочные строковые значения могут быть записаны как 'строковый блок' (используя |), +# или как 'сложенный блок' (используя '>'). +literal_block: | + Значение всего текста в этом блоке будет присвоено ключу 'literal_block', + с сохранением переноса строк. + + Объявление продолжается до удаления отступа и выравнивания с ведущим отступом. + + Любые строки с большим отступом сохраняют остатки своего отступа - + эта строка будет содержать дополнительно 4 пробела. +folded_style: > + Весь блок этого тектса будет значением 'folded_style', но в данном случае + все символы новой строки будут заменены пробелами. + + Пустые строки будут преобразованы в перенос строки. + + Строки с дополнительными отступами сохраняют их переносы строк - + этот текст появится через 2 строки. + +################## +# Типы коллекций # +################## + +# Вложения используют отступы. Отступ в 2 пробела предпочтителен (но не обязателен). +a_nested_map: + key: value + another_key: Another Value + another_nested_map: + hello: hello + +# В словарях (maps) используются не только строковые значения ключей. +0.25: a float key + +# Ключи также могут быть сложными, например многострочными. +# Мы используем ? с последующим пробелом чтобы обозначить начало сложного ключа. +? | + Этот ключ + который содержит несколько строк +: и это его значение + +# YAML также разрешает соответствия между последовательностями со сложными ключами +# Некоторые парсеры могут выдать предупреждения или ошибку +# Пример +? - Manchester United + - Real Madrid +: [2001-01-01, 2002-02-02] + +# Последовательности (эквивалент списка или массива) выглядят как-то так +# (обратите внимание что знак '-' считается отступом): +a_sequence: + - Item 1 + - Item 2 + - 0.5 # последовательности могут содержать различные типы. + - Item 4 + - key: value + another_key: another_value + - + - Это последовательность + - внутри другой последовательности + - - - Объявления вложенных последовательностей + - могут быть сжаты + +# Поскольку YAML это надмножество JSON, вы можете использовать JSON-подобный +# синтаксис для словарей и последовательностей: +json_map: {"key": "value"} +json_seq: [3, 2, 1, "takeoff"] +в данном случае кавычки не обязательны: {key: [3, 2, 1, takeoff]} + +########################## +# Дополнительные функции # +########################## + +# В YAML есть удобная система так называемых 'якорей' (anchors), которые позволяют легко +# дублировать содержимое внутри документа. Оба ключа в примере будут иметь одинаковые значения: +anchored_content: &anchor_name Эта строка будет являться значением обоих ключей. +other_anchor: *anchor_name + +# Якоря могут использоваться для дублирования/наследования свойств +base: &base + name: Каждый будет иметь одинаковое имя + +# Регулярное выражение << называется ключом объединения независимо от типа языка. +# Он используется чтобы показать что все ключи одного или более словарей должны быть +# добавлены в текущий словарь. + +foo: &foo + <<: *base + age: 10 + +bar: &bar + <<: *base + age: 20 + +# foo и bar могли бы иметь имена: Каждый из них имеет аналогичное имя + +# В YAML есть теги (tags), которые используются для явного объявления типов. +explicit_string: !!str 0.5 +# В некоторых парсерах реализованы теги для конкретного языка, пример для Python +# пример сложного числового типа. +python_complex_number: !!python/complex 1+2j + +# Мы можем использовать сложные ключи с включенными в них тегами из определенного языка +? !!python/tuple [5, 7] +: Fifty Seven +# Могло бы быть {(5, 7): 'Fifty Seven'} в Python + +####################### +# Дополнительные типы # +####################### + +# Строки и числа не единственные величины которые может понять YAML. +# YAML также поддерживает даты и время в формате ISO. +datetime: 2001-12-15T02:59:43.1Z +datetime_with_spaces: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 + +# Тег !!binary показывает что эта строка является base64-закодированным +# представлением двоичного объекта. +gif_file: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + +# YAML может использовать объекты типа ассоциативных массивов (set), как представлено ниже: +set: + ? item1 + ? item2 + ? item3 +or: {item1, item2, item3} + +# Сеты (set) являются простыми эквивалентами словарей со значениями +# типа null; запись выше эквивалентна следующей: +set2: + item1: null + item2: null + item3: null + +... # конец документа +``` + +### Больше информации + ++ [YAML оффициальный вебсайт](http://yaml.org/) ++ [YAML онлайн валидатор](http://www.yamllint.com/) diff --git a/sl-si/asciidoc-sl.html.markdown b/sl-si/asciidoc-sl.html.markdown new file mode 100644 index 00000000..52f30fbd --- /dev/null +++ b/sl-si/asciidoc-sl.html.markdown @@ -0,0 +1,136 @@ +--- +language: asciidoc +contributors: + - ["Ryan Mavilia", "http://unoriginality.rocks/"] + - ["Abel Salgado Romero", "https://twitter.com/abelsromero"] +translators: + - ["Filip Štamcar", "https://github.com/filips123"] +lang: sl-si +filename: asciidoc-sl.md +--- + +AsciiDoc je označevalni jezik, ki je podoben Markdownu in ga je mogoče uporabiti za vse od knjig do spletnih dnevnikov. Jezik, ki ga je leta 2002 ustvaril Stuart Rackham, je preprost, vendar omogoča veliko prilagoditev. + +## Glava dokumenta + +Glave so neobvezne in ne smejo vsebovati praznih vrstic. Od vsebine jih mora ločiti vsaj ena prazna vrstica. + +### Naslov + +``` += Naslov dokumenta + +Prvi stavek dokumenta. +``` + +### Naslov in avtor + +``` += Naslov dokumenta +Ime Priimek <ime.priimek@learnxinyminutes.com> + +Prvi stavek dokumenta. +``` + +### Naslov in več avtorjev + +``` + += Naslov dokumenta +Ime Priimek <ime.priimek@learnxinyminutes.com>; Janez Novak <janez.novak@pirate.com> + +Prvi stavek dokumenta. +``` + +Vrstica za revizijo + +``` += Naslov dokumenta V1 +Janez Novak <janez.novak@pirate.com> +v1.0, 2016-01-13 + +Prvi stavek dokumenta. +``` + +## Odstavki + +``` +Za odstavke ne potrebujete nič posebnega. + +Da jih ločite, dodajte prazno črto med odstavki. + +Če želite ustvariti prazno vrstico, dodajte + +in ustvarili boste prelom vrstice! +``` + +## Oblikovanje besedila + +``` +_podčrtaj za pošvno_ +*zvezdice za krepko* +*_kombinacije za zabavo_* +`krativec za monospace` +`*krepki monospace*` +``` + +## Naslovi razdelkov + +``` += Stopnja 0 (samo za naslov dokumenta) + +== Stopnja 1 <h2> + +=== Stopnja 2 <h3> + +==== Stopnja 3 <h4> + +===== Stopnja 4 <h5> + +``` + +## Seznami + +Če želite ustvariti neoštevilčen seznam, uporabite zvezdice. + +``` +* foo +* bar +* baz +``` + +Če želite ustvaril oštevilčen seznam, uporabite pike. + +``` +. predmet 1 +. predmet 2 +. predmet 3 +``` + +Seznami lahko do petkrat gnezdite tako, da dodate dodatne zvezdice ali pike. + +``` +* foo 1 +** foo 2 +*** foo 3 +**** foo 4 +***** foo 5 + +. foo 1 +.. foo 2 +... foo 3 +.... foo 4 +..... foo 5 +``` + +## Nadaljnje branje + +Obstajata dve orodji za obdelavo AsciiDoc dokumentov: + +1. [AsciiDoc](http://asciidoc.org/): izvirna implementacija v Pythonu je na voljo v glavnih distribucijah Linuxa. Stabilen in trenutno v vzdrževalnem načinu. +2. [Asciidoctor](http://asciidoctor.org/): alternativna Ruby implementacija, uporabno tudi iz Java in JavaScript. Z aktivnim razvojem si prizadeva razširiti sintakso AsciiDoc z novimi funkcijami in izhodnimi formati. + +Naslednje povezave so povezane `Asciidoctor` implementacijo: + +* [Markdown - AsciiDoc syntax comparison](http://asciidoctor.org/docs/user-manual/#comparison-by-example): primerjava skupnih elementov Markdowna in AsciiDoca. +* [Getting started](http://asciidoctor.org/docs/#get-started-with-asciidoctor): namestitev in navodila, ki omogočajo enostavne dokumente. +* [Asciidoctor User Manual](http://asciidoctor.org/docs/user-manual/): popolni priročnik z enim dokumentom s sklicevanjem na sintakso, primeri in oridji za upodabljanje. diff --git a/smalltalk.html.markdown b/smalltalk.html.markdown index 87135cf4..ae7ecb0e 100644 --- a/smalltalk.html.markdown +++ b/smalltalk.html.markdown @@ -2,7 +2,7 @@ language: Smalltalk filename: smalltalk.st contributors: - - ["Jigyasa Grover", "https://github.com/jig08"] + - ["Jigyasa Grover", "https://github.com/jigyasa-grover"] - ["tim Rowledge", "tim@rowledge.org"] --- @@ -10,18 +10,19 @@ contributors: - Smalltalk was created as the language to underpin the "new world" of computing exemplified by "human–computer symbiosis." - It was designed and created in part for educational use, more so for constructionist learning, at the Learning Research Group (LRG) of Xerox PARC by Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, Scott Wallace, and others during the 1970s. -Feedback highly appreciated! Reach me at [@jigyasa_grover](https://twitter.com/jigyasa_grover) or send me an e-mail at `grover.jigyasa1@gmail.com`. +`Feedback highly appreciated! Reach me at [@jigyasa_grover](https://twitter.com/jigyasa_grover) or send me an e-mail at grover.jigyasa1@gmail.com.` ## The Basics + ### Everything is an object Yes, everything. Integers are instances of one of the numeric classes. Classes are instances of the class Metaclass and are just as manipulable as any other object. All classes are part of a single class tree; no disjoint class trees. Stack frames are objects and can be manipulated, which is how the debugger works. There are no pointers into memory locations that you can dereference and mess with. ### Functions are not called; messages are sent to objects -Work is done by sending messages to objects, which decide how to respond to that message and run a method as a result, which eventually returns some object to the original message sending code. -The system knows the class of the object receiving a message and looks up the message in that class's list of methods. If it is not found, the lookup continues in the super class until either it is found or the root of the classes is reached and there is still no relevant method. -If a suitable method is found the code is run, and the same process keeps on going with all the methods sent by that method and so on forever. -If no suitable method is found an exception is raised, which typically results in a user interface notifier to tell the user that the message was not understood. It is entirely possible to catch the exception and do something to fix the problem, which might range from 'ignore it' to 'load some new packages for this class and try again'. -A method (more strictly an instance of the class CompiledMethod) is a chunk of Smalltalk code that has been compiled into bytecodes. Executing methods start at the beginning and return to the sender when a return is encountered (we use ^ to signify 'return the follwing object') or the end of the code is reached, in which case the current object running the code is returned. +- Work is done by sending messages to objects, which decide how to respond to that message and run a method as a result, which eventually returns some object to the original message sending code. +- The system knows the class of the object receiving a message and looks up the message in that class's list of methods. If it is not found, the lookup continues in the super class until either it is found or the root of the classes is reached and there is still no relevant method. +- If a suitable method is found the code is run, and the same process keeps on going with all the methods sent by that method and so on forever. +- If no suitable method is found an exception is raised, which typically results in a user interface notifier to tell the user that the message was not understood. It is entirely possible to catch the exception and do something to fix the problem, which might range from 'ignore it' to 'load some new packages for this class and try again'. +- A method (more strictly an instance of the class CompiledMethod) is a chunk of Smalltalk code that has been compiled into bytecodes. Executing methods start at the beginning and return to the sender when a return is encountered (we use ^ to signify 'return the follwing object') or the end of the code is reached, in which case the current object running the code is returned. ### Simple syntax Smalltalk has a simple syntax with very few rules. @@ -55,7 +56,9 @@ self size > 4 ifTrue: [^argumentObject sizeRelatingTo: self]. ``` Everything here except the `^` involves sending more messages. Event the `ifTrue:` that you might think is a language control structure is just Smalltalk code. + We start by sending `size` to `self`. `self` is the object currently running the code - so in this case it is the myObject we started with. `size` is a very common message that we might anticipate tells us something about how big an object is; you could look it up with the Smalltalk tools very simply. The result we get is then sent the message `>` with the plain old integer 4 (which is an object too; no strange primitive types to pollute the system here) and nobody should be surprised the `>` is a comparison that answers true or false. That boolean (which is actually a Boolean object in Smalltalk) is sent the message `ifTrue:` with the block of code between the `[]` as its argument; obvioulsy a true boolean might be expected to run that block of code and a false to ignore it. + If the block is run then we do some more message sending to the argument object and noting the `^` we return the answer back to our starting point and it gets assigned to `result`. If the block is ignored we seem to run out of code and so `self` is returned and assigned to `result`. ## Smalltalk quick reference cheat-sheet @@ -92,179 +95,178 @@ Taken from [Smalltalk Cheatsheet](http://www.angelfire.com/tx4/cus/notes/smallta #### Transcript: ``` -Transcript clear. "clear to transcript window" -Transcript show: 'Hello World'. "output string in transcript window" -Transcript nextPutAll: 'Hello World'. "output string in transcript window" -Transcript nextPut: $A. "output character in transcript window" -Transcript space. "output space character in transcript window" -Transcript tab. "output tab character in transcript window" -Transcript cr. "carriage return / linefeed" -'Hello' printOn: Transcript. "append print string into the window" -'Hello' storeOn: Transcript. "append store string into the window" -Transcript endEntry. "flush the output buffer" +Transcript clear. "clear to transcript window" +Transcript show: 'Hello World'. "output string in transcript window" +Transcript nextPutAll: 'Hello World'. "output string in transcript window" +Transcript nextPut: $A. "output character in transcript window" +Transcript space. "output space character in transcript window" +Transcript tab. "output tab character in transcript window" +Transcript cr. "carriage return / linefeed" +'Hello' printOn: Transcript. "append print string into the window" +'Hello' storeOn: Transcript. "append store string into the window" +Transcript endEntry. "flush the output buffer" ``` #### Assignment: ``` | x y | -x _ 4. "assignment (Squeak) <-" -x := 5. "assignment" -x := y := z := 6. "compound assignment" +x _ 4. "assignment (Squeak) <-" +x := 5. "assignment" +x := y := z := 6. "compound assignment" x := (y := 6) + 1. -x := Object new. "bind to allocated instance of a class" -x := 123 class. "discover the object class" -x := Integer superclass. "discover the superclass of a class" -x := Object allInstances. "get an array of all instances of a class" -x := Integer allSuperclasses. "get all superclasses of a class" -x := 1.2 hash. "hash value for object" -y := x copy. "copy object" -y := x shallowCopy. "copy object (not overridden)" -y := x deepCopy. "copy object and instance vars" -y := x veryDeepCopy. "complete tree copy using a dictionary" +x := Object new. "bind to allocated instance of a class" +x := 123 class. "discover the object class" +x := Integer superclass. "discover the superclass of a class" +x := Object allInstances. "get an array of all instances of a class" +x := Integer allSuperclasses. "get all superclasses of a class" +x := 1.2 hash. "hash value for object" +y := x copy. "copy object" +y := x shallowCopy. "copy object (not overridden)" +y := x deepCopy. "copy object and instance vars" +y := x veryDeepCopy. "complete tree copy using a dictionary" ``` #### Constants: ``` | b | -b := true. "true constant" -b := false. "false constant" -x := nil. "nil object constant" -x := 1. "integer constants" -x := 3.14. "float constants" -x := 2e-2. "fractional constants" -x := 16r0F. "hex constant". -x := -1. "negative constants" -x := 'Hello'. "string constant" -x := 'I''m here'. "single quote escape" -x := $A. "character constant" -x := $ . "character constant (space)" -x := #aSymbol. "symbol constants" -x := #(3 2 1). "array constants" -x := #('abc' 2 $a). "mixing of types allowed" +b := true. "true constant" +b := false. "false constant" +x := nil. "nil object constant" +x := 1. "integer constants" +x := 3.14. "float constants" +x := 2e-2. "fractional constants" +x := 16r0F. "hex constant". +x := -1. "negative constants" +x := 'Hello'. "string constant" +x := 'I''m here'. "single quote escape" +x := $A. "character constant" +x := $ . "character constant (space)" +x := #aSymbol. "symbol constants" +x := #(3 2 1). "array constants" +x := #('abc' 2 $a). "mixing of types allowed" ``` #### Booleans: ``` | b x y | x := 1. y := 2. -b := (x = y). "equals" -b := (x ~= y). "not equals" -b := (x == y). "identical" -b := (x ~~ y). "not identical" -b := (x > y). "greater than" -b := (x < y). "less than" -b := (x >= y). "greater than or equal" -b := (x <= y). "less than or equal" -b := b not. "boolean not" -b := (x < 5) & (y > 1). "boolean and" -b := (x < 5) | (y > 1). "boolean or" -b := (x < 5) and: [y > 1]. "boolean and (short-circuit)" -b := (x < 5) or: [y > 1]. "boolean or (short-circuit)" -b := (x < 5) eqv: (y > 1). "test if both true or both false" -b := (x < 5) xor: (y > 1). "test if one true and other false" -b := 5 between: 3 and: 12. "between (inclusive)" -b := 123 isKindOf: Number. "test if object is class or subclass of" -b := 123 isMemberOf: SmallInteger. "test if object is type of class" -b := 123 respondsTo: sqrt. "test if object responds to message" -b := x isNil. "test if object is nil" -b := x isZero. "test if number is zero" -b := x positive. "test if number is positive" -b := x strictlyPositive. "test if number is greater than zero" -b := x negative. "test if number is negative" -b := x even. "test if number is even" -b := x odd. "test if number is odd" -b := x isLiteral. "test if literal constant" -b := x isInteger. "test if object is integer" -b := x isFloat. "test if object is float" -b := x isNumber. "test if object is number" -b := $A isUppercase. "test if upper case character" -b := $A isLowercase. "test if lower case character" +b := (x = y). "equals" +b := (x ~= y). "not equals" +b := (x == y). "identical" +b := (x ~~ y). "not identical" +b := (x > y). "greater than" +b := (x < y). "less than" +b := (x >= y). "greater than or equal" +b := (x <= y). "less than or equal" +b := b not. "boolean not" +b := (x < 5) & (y > 1). "boolean and" +b := (x < 5) | (y > 1). "boolean or" +b := (x < 5) and: [y > 1]. "boolean and (short-circuit)" +b := (x < 5) or: [y > 1]. "boolean or (short-circuit)" +b := (x < 5) eqv: (y > 1). "test if both true or both false" +b := (x < 5) xor: (y > 1). "test if one true and other false" +b := 5 between: 3 and: 12. "between (inclusive)" +b := 123 isKindOf: Number. "test if object is class or subclass of" +b := 123 isMemberOf: SmallInteger. "test if object is type of class" +b := 123 respondsTo: sqrt. "test if object responds to message" +b := x isNil. "test if object is nil" +b := x isZero. "test if number is zero" +b := x positive. "test if number is positive" +b := x strictlyPositive. "test if number is greater than zero" +b := x negative. "test if number is negative" +b := x even. "test if number is even" +b := x odd. "test if number is odd" +b := x isLiteral. "test if literal constant" +b := x isInteger. "test if object is integer" +b := x isFloat. "test if object is float" +b := x isNumber. "test if object is number" +b := $A isUppercase. "test if upper case character" +b := $A isLowercase. "test if lower case character" ``` #### Arithmetic expressions: ``` | x | -x := 6 + 3. "addition" -x := 6 - 3. "subtraction" -x := 6 * 3. "multiplication" -x := 1 + 2 * 3. "evaluation always left to right (1 + 2) * 3" -x := 5 / 3. "division with fractional result" -x := 5.0 / 3.0. "division with float result" -x := 5.0 // 3.0. "integer divide" -x := 5.0 \\ 3.0. "integer remainder" -x := -5. "unary minus" -x := 5 sign. "numeric sign (1, -1 or 0)" -x := 5 negated. "negate receiver" -x := 1.2 integerPart. "integer part of number (1.0)" -x := 1.2 fractionPart. "fractional part of number (0.2)" -x := 5 reciprocal. "reciprocal function" -x := 6 * 3.1. "auto convert to float" -x := 5 squared. "square function" -x := 25 sqrt. "square root" -x := 5 raisedTo: 2. "power function" -x := 5 raisedToInteger: 2. "power function with integer" -x := 5 exp. "exponential" -x := -5 abs. "absolute value" -x := 3.99 rounded. "round" -x := 3.99 truncated. "truncate" -x := 3.99 roundTo: 1. "round to specified decimal places" -x := 3.99 truncateTo: 1. "truncate to specified decimal places" -x := 3.99 floor. "truncate" -x := 3.99 ceiling. "round up" -x := 5 factorial. "factorial" -x := -5 quo: 3. "integer divide rounded toward zero" -x := -5 rem: 3. "integer remainder rounded toward zero" -x := 28 gcd: 12. "greatest common denominator" -x := 28 lcm: 12. "least common multiple" -x := 100 ln. "natural logarithm" -x := 100 log. "base 10 logarithm" -x := 100 log: 10. "logarithm with specified base" -x := 100 floorLog: 10. "floor of the log" -x := 180 degreesToRadians. "convert degrees to radians" -x := 3.14 radiansToDegrees. "convert radians to degrees" -x := 0.7 sin. "sine" -x := 0.7 cos. "cosine" -x := 0.7 tan. "tangent" -x := 0.7 arcSin. "arcsine" -x := 0.7 arcCos. "arccosine" -x := 0.7 arcTan. "arctangent" -x := 10 max: 20. "get maximum of two numbers" -x := 10 min: 20. "get minimum of two numbers" -x := Float pi. "pi" -x := Float e. "exp constant" -x := Float infinity. "infinity" -x := Float nan. "not-a-number" -x := Random new next; yourself. x next. "random number stream (0.0 to 1.0)" -x := 100 atRandom. "quick random number" +x := 6 + 3. "addition" +x := 6 - 3. "subtraction" +x := 6 * 3. "multiplication" +x := 1 + 2 * 3. "evaluation always left to right (1 + 2) * 3" +x := 5 / 3. "division with fractional result" +x := 5.0 / 3.0. "division with float result" +x := 5.0 // 3.0. "integer divide" +x := 5.0 \\ 3.0. "integer remainder" +x := -5. "unary minus" +x := 5 sign. "numeric sign (1, -1 or 0)" +x := 5 negated. "negate receiver" +x := 1.2 integerPart. "integer part of number (1.0)" +x := 1.2 fractionPart. "fractional part of number (0.2)" +x := 5 reciprocal. "reciprocal function" +x := 6 * 3.1. "auto convert to float" +x := 5 squared. "square function" +x := 25 sqrt. "square root" +x := 5 raisedTo: 2. "power function" +x := 5 raisedToInteger: 2. "power function with integer" +x := 5 exp. "exponential" +x := -5 abs. "absolute value" +x := 3.99 rounded. "round" +x := 3.99 truncated. "truncate" +x := 3.99 roundTo: 1. "round to specified decimal places" +x := 3.99 truncateTo: 1. "truncate to specified decimal places" +x := 3.99 floor. "truncate" +x := 3.99 ceiling. "round up" +x := 5 factorial. "factorial" +x := -5 quo: 3. "integer divide rounded toward zero" +x := -5 rem: 3. "integer remainder rounded toward zero" +x := 28 gcd: 12. "greatest common denominator" +x := 28 lcm: 12. "least common multiple" +x := 100 ln. "natural logarithm" +x := 100 log. "base 10 logarithm" +x := 100 log: 10. "floor of the log" +x := 180 degreesToRadians. "convert degrees to radians" +x := 3.14 radiansToDegrees. "convert radians to degrees" +x := 0.7 sin. "sine" +x := 0.7 cos. "cosine" +x := 0.7 tan. "tangent" +x := 0.7 arcSin. "arcsine" +x := 0.7 arcCos. "arccosine" +x := 0.7 arcTan. "arctangent" +x := 10 max: 20. "get maximum of two numbers" +x := 10 min: 20. "get minimum of two numbers" +x := Float pi. "pi" +x := Float e. "exp constant" +x := Float infinity. "infinity" +x := Float nan. "not-a-number" +x := Random new next; yourself. x next. "random number stream (0.0 to 1.0)" +x := 100 atRandom. "quick random number" ``` #### Bitwise Manipulation: ``` | b x | -x := 16rFF bitAnd: 16r0F. "and bits" -x := 16rF0 bitOr: 16r0F. "or bits" -x := 16rFF bitXor: 16r0F. "xor bits" -x := 16rFF bitInvert. "invert bits" -x := 16r0F bitShift: 4. "left shift" -x := 16rF0 bitShift: -4. "right shift" -"x := 16r80 bitAt: 7." "bit at position (0|1) [!Squeak]" -x := 16r80 highbit. "position of highest bit set" -b := 16rFF allMask: 16r0F. "test if all bits set in mask set in receiver" -b := 16rFF anyMask: 16r0F. "test if any bits set in mask set in receiver" -b := 16rFF noMask: 16r0F. "test if all bits set in mask clear in receiver" +x := 16rFF bitAnd: 16r0F. "and bits" +x := 16rF0 bitOr: 16r0F. "or bits" +x := 16rFF bitXor: 16r0F. "xor bits" +x := 16rFF bitInvert. "invert bits" +x := 16r0F bitShift: 4. "left shift" +x := 16rF0 bitShift: -4. "right shift" +"x := 16r80 bitAt: 7." "bit at position (0|1) [!Squeak]" +x := 16r80 highbit. "position of highest bit set" +b := 16rFF allMask: 16r0F. "test if all bits set in mask set in receiver" +b := 16rFF anyMask: 16r0F. "test if any bits set in mask set in receiver" +b := 16rFF noMask: 16r0F. "test if all bits set in mask clear in receiver" ``` #### Conversion: ``` | x | -x := 3.99 asInteger. "convert number to integer (truncates in Squeak)" -x := 3.99 asFraction. "convert number to fraction" -x := 3 asFloat. "convert number to float" -x := 65 asCharacter. "convert integer to character" -x := $A asciiValue. "convert character to integer" -x := 3.99 printString. "convert object to string via printOn:" -x := 3.99 storeString. "convert object to string via storeOn:" -x := 15 radix: 16. "convert to string in given base" +x := 3.99 asInteger. "convert number to integer (truncates in Squeak)" +x := 3.99 asFraction. "convert number to fraction" +x := 3 asFloat. "convert number to float" +x := 65 asCharacter. "convert integer to character" +x := $A asciiValue. "convert character to integer" +x := 3.99 printString. "convert object to string via printOn:" +x := 3.99 storeString. "convert object to string via storeOn:" +x := 15 radix: 16. "convert to string in given base" x := 15 printStringBase: 16. x := 15 storeStringBase: 16. ``` @@ -284,6 +286,7 @@ x := 15 storeStringBase: 16. x := [ y := 1. z := 2. ]. x value. "simple block usage" x := [ :argOne :argTwo | argOne, ' and ' , argTwo.]. "set up block with argument passing" Transcript show: (x value: 'First' value: 'Second'); cr. "use block with argument passing" + "x := [ | z | z := 1.]. *** localvars not available in squeak blocks" ``` @@ -303,27 +306,31 @@ Transcript show: (x value: 'First' value: 'Second'); cr. "use block with argu ``` | x | -x := 2 sqrt. "unary message" -x := 2 raisedTo: 10. "keyword message" -x := 194 * 9. "binary message" -Transcript show: (194 * 9) printString; cr. "combination (chaining)" -x := 2 perform: #sqrt. "indirect method invocation" -Transcript "Cascading - send multiple messages to receiver" +x := 2 sqrt. "unary message" +x := 2 raisedTo: 10. "keyword message" +x := 194 * 9. "binary message" +Transcript show: (194 * 9) printString; cr. "combination (chaining)" +x := 2 perform: #sqrt. "indirect method invocation" +Transcript "Cascading - send multiple messages to receiver" show: 'hello '; show: 'world'; cr. -x := 3 + 2; * 100. "result=300. Sends message to same receiver (3)" +x := 3 + 2; * 100. "result=300. Sends message to same receiver (3)" ``` #### Conditional Statements: ``` | x | -x > 10 ifTrue: [Transcript show: 'ifTrue'; cr]. "if then" -x > 10 ifFalse: [Transcript show: 'ifFalse'; cr]. "if else" -x > 10 "if then else" +x > 10 ifTrue: [Transcript show: 'ifTrue'; cr]. "if then" +x > 10 ifFalse: [Transcript show: 'ifFalse'; cr]. "if else" + +"if then else" +x > 10 ifTrue: [Transcript show: 'ifTrue'; cr] ifFalse: [Transcript show: 'ifFalse'; cr]. -x > 10 "if else then" + +"if else then" +x > 10 ifFalse: [Transcript show: 'ifFalse'; cr] ifTrue: [Transcript show: 'ifTrue'; cr]. Transcript @@ -332,7 +339,9 @@ Transcript ifTrue: ['ifTrue'] ifFalse: ['ifFalse']); cr. -Transcript "nested if then else" + +"nested if then else" +Transcript show: (x > 10 ifTrue: [x > 5 @@ -340,7 +349,9 @@ Transcript "nested if then else ifFalse: ['B']] ifFalse: ['C']); cr. -switch := Dictionary new. "switch functionality" + +"switch functionality" +switch := Dictionary new. switch at: $A put: [Transcript show: 'Case A'; cr]. switch at: $B put: [Transcript show: 'Case B'; cr]. switch at: $C put: [Transcript show: 'Case C'; cr]. @@ -351,129 +362,129 @@ result := (switch at: $B) value. ``` | x y | x := 4. y := 1. -[x > 0] whileTrue: [x := x - 1. y := y * 2]. "while true loop" -[x >= 4] whileFalse: [x := x + 1. y := y * 2]. "while false loop" -x timesRepeat: [y := y * 2]. "times repeat loop (i := 1 to x)" -1 to: x do: [:a | y := y * 2]. "for loop" -1 to: x by: 2 do: [:a | y := y / 2]. "for loop with specified increment" -#(5 4 3) do: [:a | x := x + a]. "iterate over array elements" +[x > 0] whileTrue: [x := x - 1. y := y * 2]. "while true loop" +[x >= 4] whileFalse: [x := x + 1. y := y * 2]. "while false loop" +x timesRepeat: [y := y * 2]. "times repeat loop (i := 1 to x)" +1 to: x do: [:a | y := y * 2]. "for loop" +1 to: x by: 2 do: [:a | y := y / 2]. "for loop with specified increment" +#(5 4 3) do: [:a | x := x + a]. "iterate over array elements" ``` #### Character: ``` | x y | -x := $A. "character assignment" -y := x isLowercase. "test if lower case" -y := x isUppercase. "test if upper case" -y := x isLetter. "test if letter" -y := x isDigit. "test if digit" -y := x isAlphaNumeric. "test if alphanumeric" -y := x isSeparator. "test if separator char" -y := x isVowel. "test if vowel" -y := x digitValue. "convert to numeric digit value" -y := x asLowercase. "convert to lower case" -y := x asUppercase. "convert to upper case" -y := x asciiValue. "convert to numeric ascii value" -y := x asString. "convert to string" -b := $A <= $B. "comparison" +x := $A. "character assignment" +y := x isLowercase. "test if lower case" +y := x isUppercase. "test if upper case" +y := x isLetter. "test if letter" +y := x isDigit. "test if digit" +y := x isAlphaNumeric. "test if alphanumeric" +y := x isSeparator. "test if separator char" +y := x isVowel. "test if vowel" +y := x digitValue. "convert to numeric digit value" +y := x asLowercase. "convert to lower case" +y := x asUppercase. "convert to upper case" +y := x asciiValue. "convert to numeric ascii value" +y := x asString. "convert to string" +b := $A <= $B. "comparison" y := $A max: $B. ``` #### Symbol: ``` | b x y | -x := #Hello. "symbol assignment" -y := 'String', 'Concatenation'. "symbol concatenation (result is string)" -b := x isEmpty. "test if symbol is empty" -y := x size. "string size" -y := x at: 2. "char at location" -y := x copyFrom: 2 to: 4. "substring" -y := x indexOf: $e ifAbsent: [0]. "first position of character within string" -x do: [:a | Transcript show: a printString; cr]. "iterate over the string" -b := x conform: [:a | (a >= $a) & (a <= $z)]. "test if all elements meet condition" -y := x select: [:a | a > $a]. "return all elements that meet condition" -y := x asString. "convert symbol to string" -y := x asText. "convert symbol to text" -y := x asArray. "convert symbol to array" -y := x asOrderedCollection. "convert symbol to ordered collection" -y := x asSortedCollection. "convert symbol to sorted collection" -y := x asBag. "convert symbol to bag collection" -y := x asSet. "convert symbol to set collection" +x := #Hello. "symbol assignment" +y := 'String', 'Concatenation'. "symbol concatenation (result is string)" +b := x isEmpty. "test if symbol is empty" +y := x size. "string size" +y := x at: 2. "char at location" +y := x copyFrom: 2 to: 4. "substring" +y := x indexOf: $e ifAbsent: [0]. "first position of character within string" +x do: [:a | Transcript show: a printString; cr]. "iterate over the string" +b := x conform: [:a | (a >= $a) & (a <= $z)]. "test if all elements meet condition" +y := x select: [:a | a > $a]. "return all elements that meet condition" +y := x asString. "convert symbol to string" +y := x asText. "convert symbol to text" +y := x asArray. "convert symbol to array" +y := x asOrderedCollection. "convert symbol to ordered collection" +y := x asSortedCollection. "convert symbol to sorted collection" +y := x asBag. "convert symbol to bag collection" +y := x asSet. "convert symbol to set collection" ``` #### String: ``` | b x y | -x := 'This is a string'. "string assignment" -x := 'String', 'Concatenation'. "string concatenation" -b := x isEmpty. "test if string is empty" -y := x size. "string size" -y := x at: 2. "char at location" -y := x copyFrom: 2 to: 4. "substring" -y := x indexOf: $a ifAbsent: [0]. "first position of character within string" -x := String new: 4. "allocate string object" -x "set string elements" +x := 'This is a string'. "string assignment" +x := 'String', 'Concatenation'. "string concatenation" +b := x isEmpty. "test if string is empty" +y := x size. "string size" +y := x at: 2. "char at location" +y := x copyFrom: 2 to: 4. "substring" +y := x indexOf: $a ifAbsent: [0]. "first position of character within string" +x := String new: 4. "allocate string object" +x "set string elements" at: 1 put: $a; at: 2 put: $b; at: 3 put: $c; at: 4 put: $e. -x := String with: $a with: $b with: $c with: $d. "set up to 4 elements at a time" -x do: [:a | Transcript show: a printString; cr]. "iterate over the string" -b := x conform: [:a | (a >= $a) & (a <= $z)]. "test if all elements meet condition" -y := x select: [:a | a > $a]. "return all elements that meet condition" -y := x asSymbol. "convert string to symbol" -y := x asArray. "convert string to array" -x := 'ABCD' asByteArray. "convert string to byte array" -y := x asOrderedCollection. "convert string to ordered collection" -y := x asSortedCollection. "convert string to sorted collection" -y := x asBag. "convert string to bag collection" -y := x asSet. "convert string to set collection" -y := x shuffled. "randomly shuffle string" +x := String with: $a with: $b with: $c with: $d. "set up to 4 elements at a time" +x do: [:a | Transcript show: a printString; cr]. "iterate over the string" +b := x conform: [:a | (a >= $a) & (a <= $z)]. "test if all elements meet condition" +y := x select: [:a | a > $a]. "return all elements that meet condition" +y := x asSymbol. "convert string to symbol" +y := x asArray. "convert string to array" +x := 'ABCD' asByteArray. "convert string to byte array" +y := x asOrderedCollection. "convert string to ordered collection" +y := x asSortedCollection. "convert string to sorted collection" +y := x asBag. "convert string to bag collection" +y := x asSet. "convert string to set collection" +y := x shuffled. "randomly shuffle string" ``` #### Array: Fixed length collection - - ByteArray: Array limited to byte elements (0-255) - WordArray: Array limited to word elements (0-2^32) ``` | b x y sum max | -x := #(4 3 2 1). "constant array" -x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements" -x := Array new: 4. "allocate an array with specified size" -x "set array elements" +x := #(4 3 2 1). "constant array" +x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements" +x := Array new: 4. "allocate an array with specified size" +x "set array elements" at: 1 put: 5; at: 2 put: 4; at: 3 put: 3; at: 4 put: 2. -b := x isEmpty. "test if array is empty" -y := x size. "array size" -y := x at: 4. "get array element at index" -b := x includes: 3. "test if element is in array" -y := x copyFrom: 2 to: 4. "subarray" -y := x indexOf: 3 ifAbsent: [0]. "first position of element within array" -y := x occurrencesOf: 3. "number of times object in collection" -x do: [:a | Transcript show: a printString; cr]. "iterate over the array" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum array elements" -sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum array elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum array elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in array" +b := x isEmpty. "test if array is empty" +y := x size. "array size" +y := x at: 4. "get array element at index" +b := x includes: 3. "test if element is in array" +y := x copyFrom: 2 to: 4. "subarray" +y := x indexOf: 3 ifAbsent: [0]. "first position of element within array" +y := x occurrencesOf: 3. "number of times object in collection" +x do: [:a | Transcript show: a printString; cr]. "iterate over the array" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum array elements" +sum := 0. 1 to: (x size) + do: [:a | sum := sum + (x at: a)]. "sum array elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum array elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in array" ifTrue: [a] ifFalse: [c]]. -y := x shuffled. "randomly shuffle collection" -y := x asArray. "convert to array" -"y := x asByteArray." "note: this instruction not available on Squeak" -y := x asWordArray. "convert to word array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x shuffled. "randomly shuffle collection" +y := x asArray. "convert to array" +"y := x asByteArray." "note: this instruction not available on Squeak" +y := x asWordArray. "convert to word array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### OrderedCollection: @@ -481,44 +492,46 @@ acts like an expandable array ``` | b x y sum max | -x := OrderedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" -x := OrderedCollection new. "allocate collection" -x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" -y := x addFirst: 5. "add element at beginning of collection" -y := x removeFirst. "remove first element in collection" -y := x addLast: 6. "add element at end of collection" -y := x removeLast. "remove last element in collection" -y := x addAll: #(7 8 9). "add multiple elements to collection" -y := x removeAll: #(7 8 9). "remove multiple elements from collection" -x at: 2 put: 3. "set element at index" -y := x remove: 5 ifAbsent: []. "remove element from collection" -b := x isEmpty. "test if empty" -y := x size. "number of elements" -y := x at: 2. "retrieve element at index" -y := x first. "retrieve first element in collection" -y := x last. "retrieve last element in collection" -b := x includes: 5. "test if element is in collection" -y := x copyFrom: 2 to: 3. "subcollection" -y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" -y := x occurrencesOf: 3. "number of times object in collection" -x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +x := OrderedCollection + with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" +x := OrderedCollection new. "allocate collection" +x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" +y := x addFirst: 5. "add element at beginning of collection" +y := x removeFirst. "remove first element in collection" +y := x addLast: 6. "add element at end of collection" +y := x removeLast. "remove last element in collection" +y := x addAll: #(7 8 9). "add multiple elements to collection" +y := x removeAll: #(7 8 9). "remove multiple elements from collection" +x at: 2 put: 3. "set element at index" +y := x remove: 5 ifAbsent: []. "remove element from collection" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +y := x at: 2. "retrieve element at index" +y := x first. "retrieve first element in collection" +y := x last. "retrieve last element in collection" +b := x includes: 5. "test if element is in collection" +y := x copyFrom: 2 to: 3. "subcollection" +y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" +y := x occurrencesOf: 3. "number of times object in collection" +x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := 0. 1 to: (x size) + do: [:a | sum := sum + (x at: a)]. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x shuffled. "randomly shuffle collection" -y := x asArray. "convert to array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x shuffled. "randomly shuffle collection" +y := x asArray. "convert to array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### SortedCollection: @@ -526,43 +539,45 @@ like OrderedCollection except order of elements determined by sorting criteria ``` | b x y sum max | -x := SortedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" -x := SortedCollection new. "allocate collection" -x := SortedCollection sortBlock: [:a :c | a > c]. "set sort criteria" -x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" -y := x addFirst: 5. "add element at beginning of collection" -y := x removeFirst. "remove first element in collection" -y := x addLast: 6. "add element at end of collection" -y := x removeLast. "remove last element in collection" -y := x addAll: #(7 8 9). "add multiple elements to collection" -y := x removeAll: #(7 8 9). "remove multiple elements from collection" -y := x remove: 5 ifAbsent: []. "remove element from collection" -b := x isEmpty. "test if empty" -y := x size. "number of elements" -y := x at: 2. "retrieve element at index" -y := x first. "retrieve first element in collection" -y := x last. "retrieve last element in collection" -b := x includes: 4. "test if element is in collection" -y := x copyFrom: 2 to: 3. "subcollection" -y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" -y := x occurrencesOf: 3. "number of times object in collection" -x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +x := SortedCollection + with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" +x := SortedCollection new. "allocate collection" +x := SortedCollection sortBlock: [:a :c | a > c]. "set sort criteria" +x add: 3; add: 2; add: 1; add: 4; yourself. "add element to collection" +y := x addFirst: 5. "add element at beginning of collection" +y := x removeFirst. "remove first element in collection" +y := x addLast: 6. "add element at end of collection" +y := x removeLast. "remove last element in collection" +y := x addAll: #(7 8 9). "add multiple elements to collection" +y := x removeAll: #(7 8 9). "remove multiple elements from collection" +y := x remove: 5 ifAbsent: []. "remove element from collection" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +y := x at: 2. "retrieve element at index" +y := x first. "retrieve first element in collection" +y := x last. "retrieve last element in collection" +b := x includes: 4. "test if element is in collection" +y := x copyFrom: 2 to: 3. "subcollection" +y := x indexOf: 3 ifAbsent: [0]. "first position of element within collection" +y := x occurrencesOf: 3. "number of times object in collection" +x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := 0. 1 to: (x size) + do: [:a | sum := sum + (x at: a)]. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x asArray. "convert to array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x asArray. "convert to array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### Bag: @@ -570,32 +585,32 @@ like OrderedCollection except elements are in no particular order ``` | b x y sum max | -x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" -x := Bag new. "allocate collection" -x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" -x add: 3 withOccurrences: 2. "add multiple copies to collection" -y := x addAll: #(7 8 9). "add multiple elements to collection" -y := x removeAll: #(7 8 9). "remove multiple elements from collection" -y := x remove: 4 ifAbsent: []. "remove element from collection" -b := x isEmpty. "test if empty" -y := x size. "number of elements" -b := x includes: 3. "test if element is in collection" -y := x occurrencesOf: 3. "number of times object in collection" -x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" +x := Bag new. "allocate collection" +x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" +x add: 3 withOccurrences: 2. "add multiple copies to collection" +y := x addAll: #(7 8 9). "add multiple elements to collection" +y := x removeAll: #(7 8 9). "remove multiple elements from collection" +y := x remove: 4 ifAbsent: []. "remove element from collection" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +b := x includes: 3. "test if element is in collection" +y := x occurrencesOf: 3. "number of times object in collection" +x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### Set: @@ -606,60 +621,61 @@ uses identity test (== rather than =) ``` | b x y sum max | -x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" -x := Set new. "allocate collection" -x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" -y := x addAll: #(7 8 9). "add multiple elements to collection" -y := x removeAll: #(7 8 9). "remove multiple elements from collection" -y := x remove: 4 ifAbsent: []. "remove element from collection" -b := x isEmpty. "test if empty" -y := x size. "number of elements" -x includes: 4. "test if element is in collection" -x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" +x := Set new. "allocate collection" +x add: 4; add: 3; add: 1; add: 2; yourself. "add element to collection" +y := x addAll: #(7 8 9). "add multiple elements to collection" +y := x removeAll: #(7 8 9). "remove multiple elements from collection" +y := x remove: 4 ifAbsent: []. "remove element from collection" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +x includes: 4. "test if element is in collection" +x do: [:a | Transcript show: a printString; cr]. "iterate over the collection" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x asArray. "convert to array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x asArray. "convert to array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### Interval: ``` | b x y sum max | -x := Interval from: 5 to: 10. "create interval object" +x := Interval from: 5 to: 10. "create interval object" x := 5 to: 10. -x := Interval from: 5 to: 10 by: 2. "create interval object with specified increment" +x := Interval from: 5 to: 10 by: 2. "create interval object with specified increment" x := 5 to: 10 by: 2. -b := x isEmpty. "test if empty" -y := x size. "number of elements" -x includes: 9. "test if element is in collection" -x do: [:k | Transcript show: k printString; cr]. "iterate over interval" -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 7]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := 0. 1 to: (x size) do: [:a | sum := sum + (x at: a)]. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +x includes: 9. "test if element is in collection" +x do: [:k | Transcript show: k printString; cr]. "iterate over interval" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 7]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := 0. 1 to: (x size) + do: [:a | sum := sum + (x at: a)]. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x asArray. "convert to array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" +y := x asArray. "convert to array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" ``` #### Associations: @@ -676,65 +692,68 @@ uses identity test (== rather than =) ``` | b x y | -x := Dictionary new. "allocate collection" -x add: #a->4; add: #b->3; add: #c->1; add: #d->2; yourself. "add element to collection" -x at: #e put: 3. "set element at index" -b := x isEmpty. "test if empty" -y := x size. "number of elements" -y := x at: #a ifAbsent: []. "retrieve element at index" -y := x keyAtValue: 3 ifAbsent: []. "retrieve key for given value with error block" -y := x removeKey: #e ifAbsent: []. "remove element from collection" -b := x includes: 3. "test if element is in values collection" -b := x includesKey: #a. "test if element is in keys collection" -y := x occurrencesOf: 3. "number of times object in collection" -y := x keys. "set of keys" -y := x values. "bag of values" +x := Dictionary new. "allocate collection" +x add: #a->4; + add: #b->3; + add: #c->1; + add: #d->2; yourself. "add element to collection" +x at: #e put: 3. "set element at index" +b := x isEmpty. "test if empty" +y := x size. "number of elements" +y := x at: #a ifAbsent: []. "retrieve element at index" +y := x keyAtValue: 3 ifAbsent: []. "retrieve key for given value with error block" +y := x removeKey: #e ifAbsent: []. "remove element from collection" +b := x includes: 3. "test if element is in values collection" +b := x includesKey: #a. "test if element is in keys collection" +y := x occurrencesOf: 3. "number of times object in collection" +y := x keys. "set of keys" +y := x values. "bag of values" x do: [:a | Transcript show: a printString; cr]. "iterate over the values collection" x keysDo: [:a | Transcript show: a printString; cr]. "iterate over the keys collection" x associationsDo: [:a | Transcript show: a printString; cr]."iterate over the associations" x keysAndValuesDo: [:aKey :aValue | Transcript "iterate over keys and values" show: aKey printString; space; show: aValue printString; cr]. -b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" -y := x select: [:a | a > 2]. "return collection of elements that pass test" -y := x reject: [:a | a < 2]. "return collection of elements that fail test" -y := x collect: [:a | a + a]. "transform each element for new collection" -y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" -sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" -sum := x inject: 0 into: [:a :c | a + c]. "sum elements" -max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" +b := x conform: [:a | (a >= 1) & (a <= 4)]. "test if all elements meet condition" +y := x select: [:a | a > 2]. "return collection of elements that pass test" +y := x reject: [:a | a < 2]. "return collection of elements that fail test" +y := x collect: [:a | a + a]. "transform each element for new collection" +y := x detect: [:a | a > 3] ifNone: []. "find position of first element that passes test" +sum := 0. x do: [:a | sum := sum + a]. sum. "sum elements" +sum := x inject: 0 into: [:a :c | a + c]. "sum elements" +max := x inject: 0 into: [:a :c | (a > c) "find max element in collection" ifTrue: [a] ifFalse: [c]]. -y := x asArray. "convert to array" -y := x asOrderedCollection. "convert to ordered collection" -y := x asSortedCollection. "convert to sorted collection" -y := x asBag. "convert to bag collection" -y := x asSet. "convert to set collection" - -Smalltalk at: #CMRGlobal put: 'CMR entry'. "put global in Smalltalk Dictionary" -x := Smalltalk at: #CMRGlobal. "read global from Smalltalk Dictionary" -Transcript show: (CMRGlobal printString). "entries are directly accessible by name" -Smalltalk keys do: [ :k | "print out all classes" +y := x asArray. "convert to array" +y := x asOrderedCollection. "convert to ordered collection" +y := x asSortedCollection. "convert to sorted collection" +y := x asBag. "convert to bag collection" +y := x asSet. "convert to set collection" + +Smalltalk at: #CMRGlobal put: 'CMR entry'. "put global in Smalltalk Dictionary" +x := Smalltalk at: #CMRGlobal. "read global from Smalltalk Dictionary" +Transcript show: (CMRGlobal printString). "entries are directly accessible by name" +Smalltalk keys do: [ :k | "print out all classes" ((Smalltalk at: k) isKindOf: Class) ifFalse: [Transcript show: k printString; cr]]. -Smalltalk at: #CMRDictionary put: (Dictionary new). "set up user defined dictionary" -CMRDictionary at: #MyVar1 put: 'hello1'. "put entry in dictionary" -CMRDictionary add: #MyVar2->'hello2'. "add entry to dictionary use key->value combo" -CMRDictionary size. "dictionary size" -CMRDictionary keys do: [ :k | "print out keys in dictionary" +Smalltalk at: #CMRDictionary put: (Dictionary new). "set up user defined dictionary" +CMRDictionary at: #MyVar1 put: 'hello1'. "put entry in dictionary" +CMRDictionary add: #MyVar2->'hello2'. "add entry to dictionary use key->value combo" +CMRDictionary size. "dictionary size" +CMRDictionary keys do: [ :k | "print out keys in dictionary" Transcript show: k printString; cr]. -CMRDictionary values do: [ :k | "print out values in dictionary" +CMRDictionary values do: [ :k | "print out values in dictionary" Transcript show: k printString; cr]. -CMRDictionary keysAndValuesDo: [:aKey :aValue | "print out keys and values" +CMRDictionary keysAndValuesDo: [:aKey :aValue | "print out keys and values" Transcript show: aKey printString; space; show: aValue printString; cr]. -CMRDictionary associationsDo: [:aKeyValue | "another iterator for printing key values" +CMRDictionary associationsDo: [:aKeyValue | "another iterator for printing key values" Transcript show: aKeyValue printString; cr]. -Smalltalk removeKey: #CMRGlobal ifAbsent: []. "remove entry from Smalltalk dictionary" -Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary from Smalltalk dictionary" +Smalltalk removeKey: #CMRGlobal ifAbsent: []. "remove entry from Smalltalk dictionary" +Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary from Smalltalk dictionary" ``` #### Internal Stream: @@ -742,8 +761,7 @@ Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user diction | b x ios | ios := ReadStream on: 'Hello read stream'. ios := ReadStream on: 'Hello read stream' from: 1 to: 5. -[(x := ios nextLine) notNil] - whileTrue: [Transcript show: x; cr]. +[(x := ios nextLine) notNil] whileTrue: [Transcript show: x; cr]. ios position: 3. ios position. x := ios next. @@ -756,8 +774,7 @@ ios := ReadWriteStream on: 'Hello read stream' from: 1 to: 5. ios := ReadWriteStream with: 'Hello read stream'. ios := ReadWriteStream with: 'Hello read stream' from: 1 to: 10. ios position: 0. -[(x := ios nextLine) notNil] - whileTrue: [Transcript show: x; cr]. +[(x := ios nextLine) notNil] whileTrue: [Transcript show: x; cr]. ios position: 6. ios position. ios nextPutAll: 'Chris'. @@ -778,8 +795,7 @@ ios nextPutAll: 'Hello File'; cr. ios close. ios := FileStream oldFileNamed: 'ios.txt'. -[(x := ios nextLine) notNil] - whileTrue: [Transcript show: x; cr]. +[(x := ios nextLine) notNil] whileTrue: [Transcript show: x; cr]. ios position: 3. x := ios position. x := ios next. @@ -791,80 +807,80 @@ ios close. #### Date: ``` | x y | -x := Date today. "create date for today" -x := Date dateAndTimeNow. "create date from current time/date" -x := Date readFromString: '01/02/1999'. "create date from formatted string" -x := Date newDay: 12 month: #July year: 1999 "create date from parts" -x := Date fromDays: 36000. "create date from elapsed days since 1/1/1901" -y := Date dayOfWeek: #Monday. "day of week as int (1-7)" -y := Date indexOfMonth: #January. "month of year as int (1-12)" -y := Date daysInMonth: 2 forYear: 1996. "day of month as int (1-31)" -y := Date daysInYear: 1996. "days in year (365|366)" -y := Date nameOfDay: 1 "weekday name (#Monday,...)" -y := Date nameOfMonth: 1. "month name (#January,...)" -y := Date leapYear: 1996. "1 if leap year; 0 if not leap year" -y := x weekday. "day of week (#Monday,...)" -y := x previous: #Monday. "date for previous day of week" -y := x dayOfMonth. "day of month (1-31)" -y := x day. "day of year (1-366)" -y := x firstDayOfMonth. "day of year for first day of month" -y := x monthName. "month of year (#January,...)" -y := x monthIndex. "month of year (1-12)" -y := x daysInMonth. "days in month (1-31)" -y := x year. "year (19xx)" -y := x daysInYear. "days in year (365|366)" -y := x daysLeftInYear. "days left in year (364|365)" -y := x asSeconds. "seconds elapsed since 1/1/1901" -y := x addDays: 10. "add days to date object" -y := x subtractDays: 10. "subtract days to date object" -y := x subtractDate: (Date today). "subtract date (result in days)" -y := x printFormat: #(2 1 3 $/ 1 1). "print formatted date" -b := (x <= Date today). "comparison" +x := Date today. "create date for today" +x := Date dateAndTimeNow. "create date from current time/date" +x := Date readFromString: '01/02/1999'. "create date from formatted string" +x := Date newDay: 12 month: #July year: 1999 "create date from parts" +x := Date fromDays: 36000. "create date from elapsed days since 1/1/1901" +y := Date dayOfWeek: #Monday. "day of week as int (1-7)" +y := Date indexOfMonth: #January. "month of year as int (1-12)" +y := Date daysInMonth: 2 forYear: 1996. "day of month as int (1-31)" +y := Date daysInYear: 1996. "days in year (365|366)" +y := Date nameOfDay: 1 "weekday name (#Monday,...)" +y := Date nameOfMonth: 1. "month name (#January,...)" +y := Date leapYear: 1996. "1 if leap year; 0 if not leap year" +y := x weekday. "day of week (#Monday,...)" +y := x previous: #Monday. "date for previous day of week" +y := x dayOfMonth. "day of month (1-31)" +y := x day. "day of year (1-366)" +y := x firstDayOfMonth. "day of year for first day of month" +y := x monthName. "month of year (#January,...)" +y := x monthIndex. "month of year (1-12)" +y := x daysInMonth. "days in month (1-31)" +y := x year. "year (19xx)" +y := x daysInYear. "days in year (365|366)" +y := x daysLeftInYear. "days left in year (364|365)" +y := x asSeconds. "seconds elapsed since 1/1/1901" +y := x addDays: 10. "add days to date object" +y := x subtractDays: 10. "subtract days to date object" +y := x subtractDate: (Date today). "subtract date (result in days)" +y := x printFormat: #(2 1 3 $/ 1 1). "print formatted date" +b := (x <= Date today). "comparison" ``` #### Time: ``` | x y | -x := Time now. "create time from current time" -x := Time dateAndTimeNow. "create time from current time/date" -x := Time readFromString: '3:47:26 pm'. "create time from formatted string" -x := Time fromSeconds: (60 * 60 * 4). "create time from elapsed time from midnight" -y := Time millisecondClockValue. "milliseconds since midnight" -y := Time totalSeconds. "total seconds since 1/1/1901" -y := x seconds. "seconds past minute (0-59)" -y := x minutes. "minutes past hour (0-59)" -y := x hours. "hours past midnight (0-23)" -y := x addTime: (Time now). "add time to time object" -y := x subtractTime: (Time now). "subtract time to time object" -y := x asSeconds. "convert time to seconds" -x := Time millisecondsToRun: [ "timing facility" +x := Time now. "create time from current time" +x := Time dateAndTimeNow. "create time from current time/date" +x := Time readFromString: '3:47:26 pm'. "create time from formatted string" +x := Time fromSeconds: (60 * 60 * 4). "create time from elapsed time from midnight" +y := Time millisecondClockValue. "milliseconds since midnight" +y := Time totalSeconds. "total seconds since 1/1/1901" +y := x seconds. "seconds past minute (0-59)" +y := x minutes. "minutes past hour (0-59)" +y := x hours. "hours past midnight (0-23)" +y := x addTime: (Time now). "add time to time object" +y := x subtractTime: (Time now). "subtract time to time object" +y := x asSeconds. "convert time to seconds" +x := Time millisecondsToRun: [ "timing facility" 1 to: 1000 do: [:index | y := 3.14 * index]]. -b := (x <= Time now). "comparison" +b := (x <= Time now). "comparison" ``` #### Point: ``` | x y | -x := 200@100. "obtain a new point" -y := x x. "x coordinate" -y := x y. "y coordinate" -x := 200@100 negated. "negates x and y" -x := (-200@-100) abs. "absolute value of x and y" -x := (200.5@100.5) rounded. "round x and y" -x := (200.5@100.5) truncated. "truncate x and y" -x := 200@100 + 100. "add scale to both x and y" -x := 200@100 - 100. "subtract scale from both x and y" -x := 200@100 * 2. "multiply x and y by scale" -x := 200@100 / 2. "divide x and y by scale" -x := 200@100 // 2. "divide x and y by scale" -x := 200@100 \\ 3. "remainder of x and y by scale" -x := 200@100 + 50@25. "add points" -x := 200@100 - 50@25. "subtract points" -x := 200@100 * 3@4. "multiply points" -x := 200@100 // 3@4. "divide points" -x := 200@100 max: 50@200. "max x and y" -x := 200@100 min: 50@200. "min x and y" -x := 20@5 dotProduct: 10@2. "sum of product (x1*x2 + y1*y2)" +x := 200@100. "obtain a new point" +y := x x. "x coordinate" +y := x y. "y coordinate" +x := 200@100 negated. "negates x and y" +x := (-200@-100) abs. "absolute value of x and y" +x := (200.5@100.5) rounded. "round x and y" +x := (200.5@100.5) truncated. "truncate x and y" +x := 200@100 + 100. "add scale to both x and y" +x := 200@100 - 100. "subtract scale from both x and y" +x := 200@100 * 2. "multiply x and y by scale" +x := 200@100 / 2. "divide x and y by scale" +x := 200@100 // 2. "divide x and y by scale" +x := 200@100 \\ 3. "remainder of x and y by scale" +x := 200@100 + 50@25. "add points" +x := 200@100 - 50@25. "subtract points" +x := 200@100 * 3@4. "multiply points" +x := 200@100 // 3@4. "divide points" +x := 200@100 max: 50@200. "max x and y" +x := 200@100 min: 50@200. "min x and y" +x := 20@5 dotProduct: 10@2. "sum of product (x1*x2 + y1*y2)" ``` #### Rectangle: @@ -878,23 +894,24 @@ Rectangle fromUser. Display restoreAfter: [ Display fillWhite. -myPen := Pen new. "get graphic pen" +myPen := Pen new. "get graphic pen" myPen squareNib: 1. -myPen color: (Color blue). "set pen color" -myPen home. "position pen at center of display" -myPen up. "makes nib unable to draw" -myPen down. "enable the nib to draw" -myPen north. "points direction towards top" -myPen turn: -180. "add specified degrees to direction" -myPen direction. "get current angle of pen" -myPen go: 50. "move pen specified number of pixels" -myPen location. "get the pen position" -myPen goto: 200@200. "move to specified point" -myPen place: 250@250. "move to specified point without drawing" -myPen print: 'Hello World' withFont: (TextStyle default fontAt: 1). -Display extent. "get display width@height" -Display width. "get display width" -Display height. "get display height" +myPen color: (Color blue). "set pen color" +myPen home. "position pen at center of display" +myPen up. "makes nib unable to draw" +myPen down. "enable the nib to draw" +myPen north. "points direction towards top" +myPen turn: -180. "add specified degrees to direction" +myPen direction. "get current angle of pen" +myPen go: 50. "move pen specified number of pixels" +myPen location. "get the pen position" +myPen goto: 200@200. "move to specified point" +myPen place: 250@250. "move to specified point without drawing" +myPen print: 'Hello World' + withFont: (TextStyle default fontAt: 1). +Display extent. "get display width@height" +Display width. "get display width" +Display height. "get display height" ]. ``` @@ -902,6 +919,7 @@ Display height. "get display height" #### Dynamic Message Calling/Compiling: ``` | receiver message result argument keyword1 keyword2 argument1 argument2 | + "unary message" receiver := 5. message := 'factorial' asSymbol. @@ -923,11 +941,14 @@ keyword1 := 'between:' asSymbol. keyword2 := 'and:' asSymbol. argument1 := 10. argument2 := 20. + result := receiver perform: (keyword1, keyword2) asSymbol withArguments: (Array with: argument1 with: argument2). + result := Compiler evaluate: ((receiver storeString), ' ', keyword1, (argument1 storeString) , ' ', keyword2, (argument2 storeString)). + result := (Message new setSelector: (keyword1, keyword2) asSymbol @@ -935,67 +956,67 @@ result := (Message sentTo: receiver. ``` -#### Class/Meta-class: +#### Class/Meta-Class: ``` | b x | -x := String name. "class name" -x := String category. "organization category" -x := String comment. "class comment" -x := String kindOfSubclass. "subclass type - subclass: variableSubclass, etc" -x := String definition. "class definition" -x := String instVarNames. "immediate instance variable names" -x := String allInstVarNames. "accumulated instance variable names" -x := String classVarNames. "immediate class variable names" -x := String allClassVarNames. "accumulated class variable names" -x := String sharedPools. "immediate dictionaries used as shared pools" -x := String allSharedPools. "accumulated dictionaries used as shared pools" -x := String selectors. "message selectors for class" -x := String sourceCodeAt: #size. "source code for specified method" -x := String allInstances. "collection of all instances of class" -x := String superclass. "immediate superclass" -x := String allSuperclasses. "accumulated superclasses" -x := String withAllSuperclasses. "receiver class and accumulated superclasses" -x := String subclasses. "immediate subclasses" -x := String allSubclasses. "accumulated subclasses" -x := String withAllSubclasses. "receiver class and accumulated subclasses" -b := String instSize. "number of named instance variables" -b := String isFixed. "true if no indexed instance variables" -b := String isVariable. "true if has indexed instance variables" -b := String isPointers. "true if index instance vars contain objects" -b := String isBits. "true if index instance vars contain bytes/words" -b := String isBytes. "true if index instance vars contain bytes" -b := String isWords. "true if index instance vars contain words" -Object withAllSubclasses size. "get total number of class entries" +x := String name. "class name" +x := String category. "organization category" +x := String comment. "class comment" +x := String kindOfSubclass. "subclass type - subclass: variableSubclass, etc" +x := String definition. "class definition" +x := String instVarNames. "immediate instance variable names" +x := String allInstVarNames. "accumulated instance variable names" +x := String classVarNames. "immediate class variable names" +x := String allClassVarNames. "accumulated class variable names" +x := String sharedPools. "immediate dictionaries used as shared pools" +x := String allSharedPools. "accumulated dictionaries used as shared pools" +x := String selectors. "message selectors for class" +x := String sourceCodeAt: #size. "source code for specified method" +x := String allInstances. "collection of all instances of class" +x := String superclass. "immediate superclass" +x := String allSuperclasses. "accumulated superclasses" +x := String withAllSuperclasses. "receiver class and accumulated superclasses" +x := String subclasses. "immediate subclasses" +x := String allSubclasses. "accumulated subclasses" +x := String withAllSubclasses. "receiver class and accumulated subclasses" +b := String instSize. "number of named instance variables" +b := String isFixed. "true if no indexed instance variables" +b := String isVariable. "true if has indexed instance variables" +b := String isPointers. "true if index instance vars contain objects" +b := String isBits. "true if index instance vars contain bytes/words" +b := String isBytes. "true if index instance vars contain bytes" +b := String isWords. "true if index instance vars contain words" +Object withAllSubclasses size. "get total number of class entries" ``` #### Debugging: ``` | a b x | -x yourself. "returns receiver" -String browse. "browse specified class" -x inspect. "open object inspector window" +x yourself. "returns receiver" +String browse. "browse specified class" +x inspect. "open object inspector window" x confirm: 'Is this correct?'. -x halt. "breakpoint to open debugger window" +x halt. "breakpoint to open debugger window" x halt: 'Halt message'. x notify: 'Notify text'. -x error: 'Error string'. "open up error window with title" -x doesNotUnderstand: #cmrMessage. "flag message is not handled" -x shouldNotImplement. "flag message should not be implemented" -x subclassResponsibility. "flag message as abstract" -x errorImproperStore. "flag an improper store into indexable object" -x errorNonIntegerIndex. "flag only integers should be used as index" -x errorSubscriptBounds. "flag subscript out of bounds" -x primitiveFailed. "system primitive failed" - -a := 'A1'. b := 'B2'. a become: b. "switch two objects" +x error: 'Error string'. "open up error window with title" +x doesNotUnderstand: #cmrMessage. "flag message is not handled" +x shouldNotImplement. "flag message should not be implemented" +x subclassResponsibility. "flag message as abstract" +x errorImproperStore. "flag an improper store into indexable object" +x errorNonIntegerIndex. "flag only integers should be used as index" +x errorSubscriptBounds. "flag subscript out of bounds" +x primitiveFailed. "system primitive failed" + +a := 'A1'. b := 'B2'. a become: b. "switch two objects" Transcript show: a, b; cr. ``` -#### Misc +#### Miscellaneous ``` | x | -"Smalltalk condenseChanges." "compress the change file" -x := FillInTheBlank request: 'Prompt Me'. "prompt user for input" +"Smalltalk condenseChanges." "compress the change file" +x := FillInTheBlank request: 'Prompt Me'. "prompt user for input" Utilities openCommandKeyHelp ``` @@ -1016,7 +1037,7 @@ Most Smalltalks are either free as in OSS or have a free downloadable version wi * [Smalltalk-72 Manual](http://www.bitsavers.org/pdf/xerox/parc/techReports/Smalltalk-72_Instruction_Manual_Mar76.pdf) * [GNU Smalltalk User's Guide](https://www.gnu.org/software/smalltalk/manual/html_node/Tutorial.html) -#### Historical doc +#### Historical Documentation(s) * [BYTE: A Special issue on Smalltalk](https://archive.org/details/byte-magazine-1981-08) * [Smalltalk-72 Manual](http://www.bitsavers.org/pdf/xerox/parc/techReports/Smalltalk-72_Instruction_Manual_Mar76.pdf) * [Smalltalk, Objects, and Design](https://books.google.co.in/books?id=W8_Une9cbbgC&printsec=frontcover&dq=smalltalk&hl=en&sa=X&ved=0CCIQ6AEwAWoVChMIw63Vo6CpyAIV0HGOCh3S2Alf#v=onepage&q=smalltalk&f=false) diff --git a/solidity.html.markdown b/solidity.html.markdown index acf750f7..d215180d 100644 --- a/solidity.html.markdown +++ b/solidity.html.markdown @@ -5,6 +5,7 @@ contributors: - ["Nemil Dalal", "https://www.nemil.com"] - ["Joseph Chow", ""] - ["Bhoomtawath Plinsut", "https://github.com/varshard"] + - ["Shooter", "https://github.com/liushooter"] --- Solidity lets you program on [Ethereum](https://www.ethereum.org/), a @@ -237,7 +238,7 @@ uint x[][5]; // arr with 5 dynamic array elements (opp order of most languages) // Dictionaries (any type to any other type) mapping (string => uint) public balances; balances["charles"] = 1; -console.log(balances["ada"]); // is 0, all non-set key values return zeroes +// balances["ada"] result is 0, all non-set key values return zeroes // 'public' allows following from another contract contractName.balances("charles"); // returns 1 // 'public' created a getter (but not setter) like the following: @@ -403,8 +404,12 @@ event LogSent(address indexed from, address indexed to, uint amount); // note ca // Call LogSent(from, to, amount); -// For an external party (a contract or external entity), to watch using -// the Web3 Javascript library: +/** + +For an external party (a contract or external entity), to watch using +the Web3 Javascript library: + +// The following is Javascript code, not Solidity code Coin.LogSent().watch({}, '', function(error, result) { if (!error) { console.log("Coin transfer: " + result.args.amount + @@ -415,6 +420,8 @@ Coin.LogSent().watch({}, '', function(error, result) { "Receiver: " + Coin.balances.call(result.args.to)); } } +**/ + // Common paradigm for one contract to depend on another (e.g., a // contract that depends on current exchange rate provided by another) @@ -831,6 +838,7 @@ someContractAddress.callcode('function_name'); ## Additional resources - [Solidity Docs](https://solidity.readthedocs.org/en/latest/) - [Smart Contract Best Practices](https://github.com/ConsenSys/smart-contract-best-practices) +- [Superblocks Lab - Browser based IDE for Solidity](https://lab.superblocks.com/) - [EthFiddle - The JsFiddle for Solidity](https://ethfiddle.com/) - [Browser-based Solidity Editor](https://remix.ethereum.org/) - [Gitter Solidity Chat room](https://gitter.im/ethereum/solidity) diff --git a/stylus.html.markdown b/stylus.html.markdown new file mode 100644 index 00000000..1c5ddd32 --- /dev/null +++ b/stylus.html.markdown @@ -0,0 +1,228 @@ +--- +language: stylus +filename: learnStylus.styl +contributors: + - ["Salomão Neto", "https://github.com/salomaosnff"] + - ["Isaac Henrique", "https://github.com/Isaachi1"] +translators: + - ["Divay Prakash", "https://github.com/divayprakash"] +--- + +Stylus is a dynamic stylesheet preprocessor language that is compiled into CSS. It aims to add functionality to CSS without breaking compatibility across web browsers. +It does this using variables, nesting, mixins, functions and more. + +Stylus syntax is very flexible. You can use standard CSS syntax and leave the semicolon (;), colon (:) and even the ({) and (}) optional, making your code even more readable. + +Stylus does not provide new style options, but gives functionality that lets you make your CSS much more dynamic. + +```scss + +/* Code style +==============================*/ + +/* Keys, semicolon, and colon are optional in Stylus. */ + +body { + background: #000; +} + +body { + background: #000 +} + +body { + background #000 +} + +body + background #000 + +body + background: #000; + +body + background: #000 + +// Single-line comments are removed when Stylus is compiled into CSS. + +/* Multi-line comments are preserved. */ + + +/* Selectors +==============================*/ + +/* Selecting elements within another element */ +body { + background: #000000; + h1 { + color: #FF0000; + } +} + +/* Or if you prefer... */ +body + background #000000 + h1 + color #FF0000 + + +/* Getting parent element reference +==============================*/ +a { + color: #0088dd; + &:hover { + color: #DD8800; + } +} + + +/* Variables +==============================*/ + + +/* + You can store a CSS value (such as the color) of a variable. + Although it is optional, it is recommended to add $ before a variable name + so you can distinguish a variable from another CSS value. +*/ + +$primary-color = #A3A4FF +$secondary-color = #51527F +$body-font = 'Roboto', sans-serif + +/* You can use variables throughout your style sheet. +Now, if you want to change the color, you only have to make the change once. */ + +body + background-color $primary-color + color $secondary-color + font-family $body-font + +/* After compilation: */ +body { + background-color: #A3A4FF; + color: #51527F; + font-family: 'Roboto', sans-serif; +} + +/ * +This is much easier to maintain than having to change color +each time it appears throughout your style sheet. +* / + + +/* Mixins +==============================*/ + +/* If you find that you are writing the same code for more than one +element, you may want to store that code in a mixin. + +center() + display block + margin-left auto + margin-right auto + left 0 + right 0 + +/* Using the mixin */ +body { + center() + background-color: $primary-color +} + +/* After compilation: */ +div { + display: block; + margin-left: auto; + margin-right: auto; + left: 0; + right: 0; + background-color: #A3A4FF; +} + +/* You can use mixins to create a shorthand property. */ + +size($width, $height) + width $width + height $height + +.rectangle + size(100px, 60px) + +.square + size(40px, 40px) + +/* You can use a mixin as a CSS property. */ +circle($ratio) + width $ratio * 2 + height $ratio * 2 + border-radius $ratio + +.ball + circle 25px + + +/* Interpolation +==============================*/ + +vendor(prop, args) + -webkit-{prop} args + -moz-{prop} args + {prop} args + +border-radius() + vendor('border-radius', arguments) + +box-shadow() + vendor('box-shadow', arguments) + +button + border-radius 1px 2px / 3px 4px + + +/* Functions +==============================*/ + +/* Functions in Stylus allow you to perform a variety of tasks, such as recalling some data. */ + +body { + background darken(#0088DD, 50%) // Dim color #0088DD by 50% +} + +/* Creating your own function */ +add(a, b) + a + b + +body + padding add(10px, 5) + + +/* Conditions +==============================*/ +compare(a, b) + if a > b + bigger + else if a < b + smaller + else + equal + +compare(5, 2) // => bigger +compare(1, 5) // => smaller +compare(10, 10) // => equal + + +/* Iterations +==============================*/ + +/* +Repeat loop syntax for: +for <val-name> [, <key-name>] in <expression> +*/ + +for $item in (1..2) /* Repeat block 12 times */ + .col-{$item} + width ($item / 12) * 100% /* Calculate row by column number */ +``` + +Now that you know a little about this powerful CSS preprocessor, you're ready to create more dynamic style sheets. To learn more, visit the official stylus documentation at http://stylus-lang.com. diff --git a/tr-tr/clojure-tr.html.markdown b/tr-tr/clojure-tr.html.markdown new file mode 100644 index 00000000..64970945 --- /dev/null +++ b/tr-tr/clojure-tr.html.markdown @@ -0,0 +1,490 @@ +--- +language: clojure +lang: tr-tr +filename: learnclojure-tr.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Seçkin KÜKRER", "https://leavenha.github.io"] +--- + +[JVM]: https://tr.wikipedia.org/wiki/Java_sanal_makinesi +[STM]: https://en.wikipedia.org/wiki/Software_transactional_memory + +Clojure, Lisp dialekti, barınan bir dildir. [JVM][JVM] üzerinde barınıyor. Clojure, Lisp'in tüm gücü ve kendi mantalitesi ile mükemmel bir genel-amaçlı programlama dilidir. Clojure, Eş-zamanlı programlama, Makrolar, Fonksiyonel Programlama, Tembel yapılar ve daha fazlasını vaadediyor. + +(Bu örnekleri çalıştırmak için Clojure 1.2 versionu veya daha yenisine sahip olmalısınız.) + + +```clojure +; Noktalı Virgül, satırı yorumlamak için kullanılır. + +; Clojure programları formlardan meydana gelir, +; Parantezlerle çevirili değerler, boşluk ile ayrılır. --Virgül ile değil-- +; +; Clojure okuyucusu*, listedeki ilk elemanı çağırılacak bir fonksiyon +; Veya makro, geri kalan ifadeleri o çağırıma argüman olarak kabul eder. +; + +; Bir dosyadaki ilk çağırım isim-uzayı tanımlamak için `ns` olmalı. +(ns clojure-öğren) + +; +; Bir diğer yorumlama seçeneği de, ifade-içi. Bu diyez (`#`), ve alt çizgi +; İle başlar ve herhangi bir s-ifade'ye uygulanabilir. +; +#_(bu çağırım değerlendirilmeyecektir) + +; Öncelikle fonksiyon çağırımları ve temel işlemler: + +; Örnek bir fonksiyon çağırımı: +; (örnek-bir-fonksiyon ilk-argüman ikinci-argüman) + +; `str` aldığı argümanları bir karakter katarı olarak geri verir. +(str "Merhaba" " " "dünya!") ; => "Merhaba dünya!" + +; Matematik, oldukça sezgisel ve basit +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; Eşitlik için `=` +(= 1 1) ; => true +(= 2 1) ; => false + +; `not` beklediğiniz gibi, mantıksal ifadeleri tersine çevirir. +(not true) ; => false + +; Clojure formları, iç-içe çağırılabilir +; Değerlendirilen çağırımlar bir üst form'a argüman +; Olarak verilir. +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; Tipler +;;;;;;;;;;;;; + +; Clojure, Java'nın temel tipleri olan mantıksal (boolean), +; Tam sayılar (int) ve karakter katarlarını (string) kullanır. +; Değerleri denetlemek için `class` fonksiyonunu kullanın. +(class 1) ; Tam sayı sabitleri ön-tanımlı olarak `java.lang.Long` ile tanımlanır. +(class 1.); Kayan noktalı sayı sabitleri +; Ön-tanımlı olarak `java.lang.Double` ile tanımlanır. +(class ""); Karakter katarı sabitleri her zaman, --sadece-- çift tırnak +; ile tanımlanır ve ön-tanımlı olarak `java.lang.String` tipindedir. +(class false) ; Mantıksal değer sabitleri, `java.lang.Boolean`. +(class nil); "Null", (tanımsız) değerler `nil` ile tanımlanır. + +; Clojure okuyucusu her paranter ifadesini bir çağırım olarak +; değerlendirdiğinden bir liste tanımlamak için çağırımı durdurmalıyız. +'(+ 1 2) ; => (+ 1 2) +; ((quote (+ 1 2)) için bir kısa yoldur) + +; Alıntılanmış listeleri çağırabilirsiniz. +(eval '(+ 1 2)) ; => 3 + +; Koleksiyonlar ve Ardışıklar +;;;;;;;;;;;;;;;;;;; + +; Listeler bağlı-liste veri yapısı, +; Vektörler dizi altyapısı kullanır. +(class '(1 2 3)); => clojure.lang.PersistentList +(class [1 2 3]); => clojure.lang.PersistentVector + +; Bir liste `(1 2 3)` şeklinde gösterilebilir, yazılabilir. +; Fakat bu listeyi, Alıntılamalıyız --Quote--. +; Bu, onu bir fonksiyon çağırımı olarak değil, +; bir liste olarak değerlendirilmesini sağlayacaktır. +; Ayrıca, `(list 1 2 3)` tamamen `'(1 2 3)` ifadesi ile +; eşdeğerdir. + +; 'Koleksiyonlar' sadece bir veri grubudur. +; Vektörler ve Listeler, koleksiyondur: +(coll? '(1 2 3)) ; => true +(coll? [1 2 3]) ; => true + +; 'Ardışıklar' (seqs), bir veri listesinin soyut tanımlamasıdır. +; Sadece listeler ardışıktır. +(seq? '(1 2 3)) ; => true +(seq? [1 2 3]) ; => false + +; Bir ardışık, ulaşıldığında sadece giriş verisi vermelidir. +; Yani, ardışıklar tembel olabilir. | Sonsuz ardışıklar tanımlanabilir. +(range 4) ; => (0 1 2 3) +(range) ; => (0 1 2 3 4 ...) (sonsuz bir ardışık) +(take 4 (range)) ; (0 1 2 3) + +; Bu yapılarda ekleme işlemi için `cons` kullanılır. +(cons 4 [1 2 3]) ; => (4 1 2 3) +(cons 4 '(1 2 3)) ; => (4 1 2 3) + +; `conj` bir koleksiyona en verimli şekilde veri ekler. +; Bu, listeler için liste başına, vektörler için ise vektör sonuna demektir. +(conj [1 2 3] 4) ; => [1 2 3 4] +(conj '(1 2 3) 4) ; => (4 1 2 3) + +; `concat` koleksiyonları birleştirmek için kullanılır. +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; `filter` ve `map` koleksiyonlarla işlem yapmak için +; ön-tanımlı yüksek-seviyeli fonksiyonlardır. +; +; ps: `inc` argümanını bir arttıran bir fonksiyon. +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; Koleksiyonları indirgemek için `reduce` kullanılır. +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; Reduce, bir ilk-tanım değeri alabilir. +(reduce conj [] '(3 2 1)) +; = (conj (conj (conj [] 3) 2) 1) +; => [3 2 1] + +; Fonksiyonlar +;;;;;;;;;;;;;;;;;;;;; + +; Yeni bir fonksiyon oluşturmak için `fn` kullanın. +; Bir fonksiyon her zaman son ifadesini döndürür. +(fn [] "Merhaba Dünya!") ; => fn + +; Fonksiyonu çağırmak için bir çift paranteze daha ihtiyaç var. +((fn [] "Merhaba Dünya!")) ; => "Merhaba Dünya!" + +; İsim uzayında bir değişken tanımlamak için `def` +; kullanılır. +(def x 1) +x ; => 1 + +; Bir değişkene fonksiyon değeri atamak için, +(def merhaba-dünya (fn [] "Merhaba Dünya!")) +(merhaba-dünya) ; => "Merhaba Dünya!" + +; Bu süreci, `defn` ile kısaltabiliriz. +(defn hello-world [] "Merhaba Dünya!") + +; `defn` fonksiyon çağırımındaki üçüncü eleman +; --vektör-- bir argüman listesidir. Fonksiyonun alacağı +; argümanları tanımlar. +(defn merhaba [isim] + (str "Merhaba " isim)) +(merhaba "Dünya!") ; => "Merhaba Dünya!" + +; Ayrıca, `#()` kısa yolunu, fonksiyon deklare etmek için +; kullanabiliriz. +(def merhaba2 #(str "Merhaba " %1)) +(merhaba2 "Dünya!") ; => "Merhaba Dünya!" + +; Çok düzeyli fonksiyonlar da tanımlanabilir, +(defn merhaba3 + ([] "Merhaba Dünya!") + ([isim] (str "Merhaba " isim))) +(merhaba3) ; => "Merhaba Dünya!" +(merhaba3 "A. NESİN!") ; => "Hello A. NESİN!" + +; Fonksiyonlar, belirsiz-sayıda argüman alabilir, +; ve bunları sizin için bir ardışıkta depolayabilir. +(defn argüman-sayısı [& argümanlarım] + (str "Verilen argüman sayısı:" (count argümanlarım) ", argümanlar: " argümanlarım)) +(argüman-sayısı "Öğün" "Çalış" "Güven") +; => "Verilen argüman sayısı:3, argümanlar: ("Öğün" "Çalış" "Güven")" + +; Elbette, sıradan ve belirsiz-sayılı fonksiyon argümanlarını +; harmanlayabilirsiniz. +(defn merhabalar [ev-sahibi & misafirler] + (str "Merhabalar, " misafirler ". Benim adım " ev-sahibi ".")) +(merhabalar "İklim" "Ayşe" "Fatma" "Nurdan") +; => "Merhabalar, (\"Ayşe\" \"Fatma\" \"Nurdan\"). Benim adım İklim." + + +; Eşlemeler +;;;;;;;;;; + +; Hash-Maps, Array-Maps +; Hash-Eşlemeleri ve Dizi-Eşlemeleri bir arayüzü paylaşırlar. +; Hash-Eşlemeleri daha hızlıdır, fakat anahtar sıralaması tutmazlar. +(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap +(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap + +; Dizi-Eşlemeleri bir çok işlem sırasında otomatik olarak Hash-Eşlemelerine +; dönüşürler. Eğer yeterince büyürlerse, endişelenmenize gerek yoktur. + +; Eşlemeler anahtar değeri olarak herhangi hash-ifadesi (hashable) +; alabilirler. Ama çoğunlukla, bu iş için anahtar-kelimeler `keyword` +; kullanılır. +; Anahtar-kelimeler, karakter katarları gibidirler, fakat +; bir kaç artıları vardır. +(class :a) ; => clojure.lang.Keyword + +(def karakterkatarı-eşlemesi {"a" 1, "b" 2, "c" 3}) +karakterkatarı-eşlemesi ; => {"a" 1, "b" 2, "c" 3} + +(def anahtar-eşlemesi {:a 1, :b 2, :c 3}) +anahtar-eşlemesi ; => {:a 1, :c 3, :b 2} + +; Bu arada, virgüller her zaman boşluk olarak değerlendirilir +; ve etkisizdirler. + +; Bir eşlemeleden fonksiyon notasyonu ile değer çağırmak, +(karakterkatarı-eşlemesi "a") ; => 1 +(anahtar-eşlemesi :a) ; => 1 + +; Keyword tipleri kendi değerlerini argüman olarak aldıkları bir +; eşlemeden değer notasyonu ile çağırabilirler. +(:b anahtar-eşlemesi) ; => 2 + +; Bu notasyonu, bir karakter katarı ile denemeyiniz. +;("a" karakterkatarı-eşlemesi) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; Verilmemiş bir değeri çağırmak, `nil` döndürecektir. +(karakterkatarı-eşlemesi "d") ; => nil + +; Eşlemelere yeni değerler eklemek için `assoc` kullanırız. +(def yeni-anahtar-eşlemesi (assoc anahtar-eşlemesi :d 4)) +yeni-anahtar-eşlemesi ; => {:a 1, :b 2, :c 3, :d 4} + +; Ama unutmayın, Clojure veri yapıları değişmezdir! +anahtar-eşlemesi ; => {:a 1, :b 2, :c 3} + +; Değer silmek için ise `dissoc` kullanılır. +(dissoc anahtar-eşlemesi :a :b) ; => {:c 3} + +; Kümeler +;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; `conj` ile bir değer eklenir. +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; `disj` ile değer çıkarılır. +(disj #{1 2 3} 1) ; => #{2 3} + +; Fonksiyon notasyonu kümelerde de tanımlıdır. +; Kendi içlerinde değer arayan bir fonksiyon olarak +; kullanılabilirler. +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; `clojure.sets` isim-uzayında daha fazla fonksiyon vardır. + +; Kullanışlı Formlar +;;;;;;;;;;;;;;;;; + +; Clojure için mantıksal yapılar bir özel-form'dur. +; Ve diğer fonksiyonlar gibi kullanılabilir. +; `if` fonksiyonunun ilk argümanı bir test ifadesidir. +(if true "ya şundadır" "ya bunda") ; => "ya şundadır" +; İkinci ifade doğru, üçüncü ifade ise yanlışsa ifadeleridir. +; Eğer test terimi doğru olarak değerlendirilirse, +; doğru ifadesi, yanlışsa yanlış ifadesi değerlendirilir ve döndürülür. +; +; Bir yanlışsa ifadesi yoksa `nil` döndürülür. +(if false "a") ; => nil + +; Yerel geçici-değişken tanımlamak için `let` kullanılır. +; İfadelerin varlığı `let` çağırımı ile sınırlıdır. +(let [a 1 b 2] + (> a b)) ; => false + +; İfade ve çağırımları `do` ile gruplayabilirsiniz. +; Çağırımların sonuncusu `do` ifadesinin değeri olarak +; döndürülecektir. +(do + (print "Selamlar!") + "Dünya!") ; => "Dünya!" (prints "Selamlar!") + +; Fonksiyonlar kapalı bir `do` ifadesi ile çevrelenmiştir. +(defn yazdır-ve-selamla! [isim] + (println "Merhaba, " isim "!") + (str "Merhaba, " isim "!")) +(yazdır-ve-selamla! "Zübeyde") ;=> "Merhaba, Zübeyde!" ("Merhaba, Zübeyde!" yazdırır.) + +; `let` ifadesi de kapalı bir `do` ile gelmektedir. +(let [isim "Ayten"] + (print "Merhabalar, " isim) + (str "Merhabalar, " isim)) ; => "Merhabalar, " ("Merhabalar, Ayten" yazdırır) + +; Sıralama-makroları (-> ve ->>) ile veri dönüşümünü daha temiz ifade +; edebilirsiniz. +; Bu makrolar ilk argümanı sonraki her çağırımın içine yerleştirir. +; +; `->` makrosu, ifadeyi çağırımların ilk argümanı olacak şekilde yerleştirir. +(-> + {:a 1 :b 2} + (assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3) + (dissoc :b)) + +; Bu ifade aşağıdaki şekilde yazılabilir: +; (dissoc (assoc {:a 1 :b 2} :c 3) :b) +; ve `{:a 1 :c 3}` olarak değer bulur. + +; Sondan-Sıralama-Makrosu (->>) ise aynı şeyi yapar, +; tek fark ise, ifadeyi, çağırımların son argümanı olarak yerleştirir. +; +(->> + (range 10) ;=> '(0 1 2 3 4 5 6 7 8 9) + (map inc) ;=> (map inc (range 10)) + (filter odd?) ;=> (filter odd? (map inc (range 10))) + (into [])) ;=> (into [] (filter odd? (map inc (range 10)))) + ; Sonuç: [1 3 5 7 9] + +; Bir ifadedeki önceki veri dönüşümlerinin sonucunu nereye +; koyacağınız konusunda daha fazla özgürlük istediğiniz bir durumda, +; Sıralama-Makrolarından daha özgür bi' şey kullanmak istersiniz; +; `as->` makrosu ile dönüşümlerin çıktısına bir isim atayabilir +; ve ardışık çağırımlarda yer tutucu olarak kullanabilirsiniz. + +(as-> [1 2 3] girdi + (map inc girdi);=> ifadeyi isterseniz çağırımın son argümanı olarak, + (nth girdi 2) ;=> veya çağırımın ilk argümanı olarak, + (conj [4 5 6] girdi [8 9 10])) ;=> ya da istediğiniz sırada kullanabilirsiniz. +;=> [4 5 6 4 [8 9 10]] + + + +; Modüller +;;;;;;;;;;;;;;; + +; `use` çağırdığınız modüldeki tüm tanımlara erişmenize olanak verir. +(use 'clojure.set) + +; Şu anda, küme fonksiyonlarını kullanabiliriz. +(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} +(difference #{1 2 3} #{2 3 4}) ; => #{1} + +; Ayrıca eklenecek fonksiyonları seçebilirsiniz de: +(use '[clojure.set :only [intersection]]) + +; Bir modülü eklemek için `require` kullanılır. +(require 'clojure.string) + +; İsim-uzayı kapsamlı çağırımlar aşağıdaki şekildedir: +; isim-uzayı/fonksiyon-ismi --isim uzayı ismi ve fonksiyon ismi +; arasına eğik çizgi koymanız yeterli. +; Burada, modül `clojure.string` ve fonksiyon ismi `blank?` +(clojure.string/blank? "") ; => true + +; Ekleme sırasında, bir modüle takma-ad verilebilir. +(require '[clojure.string :as str]) +(str/replace "Bu bir özet metindir, test için kullanılabilir!" + #"[aeıioöuü]" str/upper-case) +; => "BU bIr ÖzEt mEtIndIr, tEst IçIn kUllAnIlAbIlIr!" +; (#"", burada düzenli ifadeler için bir sözdizimsel-şekerlemeyi ifade eder) + +; Bir isim-uzayı tanımlamasında `require` kullanılabilir. +; `ns` bir makrodur ve `require` (ve `use`, ama lütfen kullanmayın) +; dahil olmak üzere bir çok çağırım için işlevsellik sağlamaktadır. +; Bu notasyonu kullanırsanız, modüllerinizi alıntılamak zorunda kalmazsınız. +(ns test + (:require + [clojure.string :as str] + [clojure.set :as set])) + + +; Java +;;;;;;;;;;;;;;;;; + +; Java, kocaman ve kullanışlı bir standart kütüphaneye sahip, +; Clojure, Java etkileşimi ile, bundan yararlanabilirsiniz. + +; `import` diğer modüller gibi, bir java modülü de ele alabilir. +; Date, bir Java modülü. +(import java.util.Date) + +; `ns` çağırımında da kullanabilirsiniz. +(ns test + (:import java.util.Date + java.util.Calendar)) + +; Bir Java nesnesinden oluşturmak için `new` çağırımını kullanabilirsiniz. +(new Date) + +; Ayrıca Clojure Okuyucusu, size bunun daha farklı bir yolunu sunar: +; Sınıf isminin sonuna koyulacak bir nokta `.` ile +; bu yapılabilir. +(Date.) ; <bir tarih nesnesi> + +; `.` --nokta-- çağırımı, size nesnelerdeki metotlara erişme imkanı verir. +(. (new Date) getTime) ; <bir zaman-damgası> +(.getTime (Date.)) ; Üstteki ifade ile tamamen aynı sonucu verir. + +; Sınıf içindeki statik metotlara erişmek için `/` ayracını +; sınıf ile metot ismi birleştirmek için kullanabilirsiniz. +; (örnekSınıf/statikMetot) +(System/currentTimeMillis) ; <bir zaman-damgası> (`system` her zaman sunulur) + +; Sınıflarla işlem yaparken, `doto` bu süreci kolaylaştırabilir. +; İlk argüman sınıf nesnesi, sonraki her çağırım, nesne üzerinde yapılır. +(import java.util.Calendar) +(doto (Calendar/getInstance) + (.set 2000 1 1 0 0 0) ; => `set` metodu, `doto` ifadesine verilen + ; sınıf nesnesi üzerinde çağırılır. + .getTime) ; => Bir tarih nesnesi. set to 2000-01-01 00:00:00 + + +; STM +;;;;;;;;;;;;;;;;; + +; 'Software Transactional Memory' Clojure'un değişmez veri yapılarını +; ele alırken kullandığı bir mekanizmadır. Clojure içinde bunu kullanan +; birkaç yapı vardır. + +; Bir `atom` en basitidir. Bir ilkleme-değeri verin. +(def benim-atomum (atom {})) + +; Bir atomu güncellemek için `swap!` kullanılır. +; `swap!` fonksiyonu, ilk argüman olarak aldığı atomu, ikinci argüman +; olarak aldığı fonksiyona uygular. Bu fonksiyona ek argümanlar ise +; fonksiyondan sonra gelirler. +(swap! benim-atomum assoc :a 1) +; benim-atomum'un değerini (assoc {} :a 1) ifadesinin sonucu ile değiştirir. +(swap! benim-atomum assoc :b 2) +; benim-atomum'un değerini (assoc {:a 1} :b 2) ifadesinin sonucu ile değiştirir. + +; `deref` ile, atomun değerini çözümleyebilirsiniz. +benim-atomum ;=> Atom<#...> (Atom ifadesi döndürür) +@benim-atomum ; => {:a 1 :b 2} + +; İşte, `atom` kullanan basit bir sayaç. +(def sayaç (atom 0)) ;=> Şu anki isim uzayına, `sayaç` ile, 0 başlangıç +; değeri ile bir atom tanımladık. +(defn sayaç-arttır [benim-atomum] + (swap! sayaç inc)) ;=> Atom'un değerini bir arttır. + +(sayaç-arttır sayaç) +(sayaç-arttır sayaç) +(sayaç-arttır sayaç) +(sayaç-arttır sayaç) +(sayaç-arttır sayaç) +(sayaç-arttır sayaç) + +@sayaç ; => 6 + +; Diğer STM yapıları `ref`'ler ve `agent`'lar. +; Ref'ler: http://clojure.org/refs +; Agent'lar: http://clojure.org/agents +``` + +### Çevirim-içi içerikler + +Bu içerik, Rich Hickey'nin derin yazılım geliştirme anlayışına ve John McCarthy'nin vizyonu olan Lisp'in, Clojure'a miras verdiklerini anlamak için elbette yeterli değildir. Fakat fonksiyonel paradigma ve bu paradigmanın modern bir Lisp lehçesinde kullanımına göz kırpmış oldunuz. + +Clojure.org, bir çok içerik ve makale var. (İngilizce içerik): +[http://clojure.org/](http://clojure.org/) + +Clojuredocs.org, örneklerle bezenmiş Clojure dökümantasyonu: +[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) + +4Clojure, interaktif bir şekilde FP ve Clojure yeteneklerinizi geliştirmenize olanak veriyor: +[http://www.4clojure.com/](http://www.4clojure.com/) + +Clojure-doc.org, Başlangıç için bir içeriklere sahip: +[http://clojure-doc.org/](http://clojure-doc.org/) + +BraveClojure, bir başka clojure öğreten web sitesi: +[https://www.braveclojure.com/](https://www.braveclojure.com/) diff --git a/tr-tr/html-tr.html.markdown b/tr-tr/html-tr.html.markdown new file mode 100644 index 00000000..b4afe7df --- /dev/null +++ b/tr-tr/html-tr.html.markdown @@ -0,0 +1,157 @@ +--- +language: html +filename: learnhtml-tr.txt +contributors: + - ["Christophe THOMAS", "https://github.com/WinChris"] +translators: + - ["Kemal MUTLU", "https://github.com/kemtake"] + - ["Nuri Akman", "https://github.com/vedia"] +lang: tr-tr +--- + +HTML, HyperText Markup Language (Hiper Metin İşaretleme Dili) anlamına gelir. + +Web sayfaları yazmamızı sağlayan bir dildir. Bu işaretleme dili, metin ve verilerin nasıl gösterilmesi gerektiği kodlanarak web sayfaları yazmamızı sağlar. Aslında, html dosyaları basit metin dosyalarıdır. + +Bu işaretleme nedir? Sayfanın verilerini, açılış etiketleri ve kapanış etiketleri ile çevreleyerek düzenleme yöntemidir. Bu işaretleme, içerdiği metne anlam vermeyi sağlar. Diğer bilgisayar dillerinde olduğu gibi, HTML’nin birçok sürümü vardır. Burada HTML5 hakkında konuşacağız. + +**NOT :** Etkilerin nasıl çalıştıklarını anlamak, çıktılarını görebilmek için [codepen](https://codepen.io/) gibi bir siteden de faydalanabilirsiniz. Bu makale temel olarak HTML sözdizimi ve bazı yararlı ipuçlarıyla ilgilidir. + +```html +<!-- Yorumlar bu satır gibi eklenir! --> + +<!-- + Yorumlar + birden + fazla + satıra + yayılabilir! +--> + +<!-- #################### Başlık #################### --> + +<!-- İşte, analiz edeceğimiz örnek bir HTML dosyası. --> + + +<!doctype html> + <html> + <head> + <title>Benim Sitem</title> + </head> + <body> + <h1>Merhaba dünya!</h1> + <a href="http://codepen.io/anon/pen/xwjLbZ"> + Bunun ne olduğuna bir bak. + </a> + <p>Bu bir paragraftır.</p> + <p>Bu başka bir paragraf.</p> + <ul> + <li>Bu, numaralandırılmamış bir listede bulunan bir öğe/maddedir (madde imi)</li> + <li>Bu başka bir öğe</li> + <li>Ve bu listedeki son öğe </li> + </ul> + </body> + </html> + +<!-- +Bir HTML dosyası, tarayıcıya her zaman sayfanın HTML olduğunu belirterek başlar. +--> +<!doctype html> + +<!-- Bundan sonra, bir <html> etiketi açılarak başlar. --> +<html> + +<!-- dosyanın sonu </html> etiketi ile kapatılır. --> +</html> + +<!-- Sayfada, bu son etiketten sonra hiçbir şey bulunmamalıdır. --> + +<!-- Açılış ve kapanış etiketleri arasında (<html> </html>) şunları bulunur: --> + +<!-- <head> ile tanımlanan bir sayfa başlığu (bu, </head> ile kapatılmalıdır). --> +<!-- Baslik, gösterilmeyen bazi aciklamalar ve ek bilgiler icerir; buna üstveri denir. --> + +<head> + <!-- <title> etiketi, tarayıcıda gösterilecek başlığı gösterir. Pencerenin başlık çubuğu ve sekme adı.--> + <title>Benim Sitem</title> +</head> + +<!-- <head> bölümünden sonra, <body> etiketi gelir. --> +<!-- Bu noktaya kadar, tarif edilen hiçbir şey tarayıcı penceresinde görünmez. --> +<!-- <body> etiketinden sonra görüntülenecek içeriğe yer verilir. --> + +<body> + <!-- h1 etiketi bir başlık oluşturur. --> + <h1>Merhaba Dünya!</h1> + <!-- + Ayrıca başlıklar <h1> etiketinden <h6> etiketine kadar gidebilir. + <h1> etiketi en önemli, <h6> etiketi en düşük öncelikli başlığı yazmamızı sağlar. + --> + + <!-- href="" özniteliğine verilen URL'ye bir köprü oluşturur. --> + <a href="http://codepen.io/anon/pen/xwjLbZ"> + Bunun ne olduğuna bir bak. + </a> + + <!-- <p> etiketi, html sayfasına metin eklememize izin verir. --> + <p>Bu bir paragraftır.</p> + <p>Bu başka bir paragraf.</p> + + <!-- <ul> etiketi bir madde imi listesi oluşturur. --> + <!-- + Numaralandırılmış bir listeye sahip olmak için <ol> etiketi de kullanılabilir. Bu durumda 1. madde 2. madde vb. şekilde gider. + --> + <ul> + <li>Bu, numaralandırılmamış bir bir liste kalemidir (madde imi)</li> + <li>Bu başka bir öğe</li> + <li>Ve bu listedeki son öğe</li> + </ul> +</body> + +<!-- İşte bir html dosyası oluşturmak bu kadar basit. --> + +<!-- Ancak birçok farklı HTML etiketi türü de eklenebilir. --> + +<!-- <img /> etiketi bir resim eklemek için kullanılır. --> +<!-- +Resmin kaynağı, src = "" özniteliği kullanılarak belirtilir. +Kaynak, bir URL veya bilgisayarınızdaki bir dosyanın yolu olabilir. +--> +<img src="http://i.imgur.com/XWG0O.gif"/> + +<!-- HTML'de bir Tablo oluşturmak da mümkündür. --> + +<!-- Bir <table> elemanı açarız. --> +<table> + + <!-- <tr> bir satır oluşturmamızı sağlar. --> + <tr> + <!-- <th> tablo sütununa bir başlık vermemize izin verir. --> + <th>Birinci Başlık</th> + <th>İkinci Başlık</th> + </tr> + + <tr> + <!-- <td> bir tablo hücresi oluşturmamızı sağlar. --> + <td>ilk satırın, ilk hücresi (sutunu)</td> + <td>ilk satırın, ikinci hücresi (sutunu)</td> + </tr> + + <tr> + <td>ikinci satırın, ilk hücresi (sutunu) </td> + <td>ikinci satırın, ikinci hücresi (sutunu)</td> + </tr> +</table> + +``` + +## Kullanım + +HTML içeriği, .html veya .htm ile biten dosyalara yazılır. Mim türü text/html . +HTML olarak yazılmış dosyalar, `.html` veya `.htm` dosya uzantısına sahiptirler. mime type'ı ise `text/html` dir. + +## Daha fazla bilgi için + +* [wikipedia](https://en.wikipedia.org/wiki/HTML) +* [HTML tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML) +* [W3School](http://www.w3schools.com/html/html_intro.asp) diff --git a/tr-tr/python-tr.html.markdown b/tr-tr/python-tr.html.markdown index 01285080..99a3eb4e 100644 --- a/tr-tr/python-tr.html.markdown +++ b/tr-tr/python-tr.html.markdown @@ -458,7 +458,7 @@ Human.grunt() #=> "*grunt*" # Modülleri sayfaya dahil edebilirsiniz import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) #=> 4.0 # Modül içerisinden spesifik bir fonksiyonu getirebilirsiniz from math import ceil, floor diff --git a/typescript.html.markdown b/typescript.html.markdown index 6feaca45..ba4a9e71 100644 --- a/typescript.html.markdown +++ b/typescript.html.markdown @@ -203,8 +203,8 @@ p1.age = 25; // Error, p1.x is read-only var p2 = { name: "John", age: 60 }; var p3: Person = p2; // Ok, read-only alias for p2 -p3.x = 35; // Error, p3.x is read-only -p2.x = 45; // Ok, but also changes p3.x because of aliasing +p3.age = 35; // Error, p3.age is read-only +p2.age = 45; // Ok, but also changes p3.age because of aliasing class Car { readonly make: string; diff --git a/uk-ua/python-ua.html.markdown b/uk-ua/python-ua.html.markdown index 2406678d..23bc1796 100644 --- a/uk-ua/python-ua.html.markdown +++ b/uk-ua/python-ua.html.markdown @@ -654,7 +654,7 @@ i.age # => виникає помилка атрибуту # Ви можете імпортувати модулі import math -print(math.sqrt(16)) # => 4 +print(math.sqrt(16)) # => 4.0 # Ви можете імпортувати окремі функції з модуля from math import ceil, floor diff --git a/vim.html.markdown b/vim.html.markdown index 0eb2c37e..5b84a3ea 100644 --- a/vim.html.markdown +++ b/vim.html.markdown @@ -94,10 +94,10 @@ that aims to make getting started with vim more approachable! Vim is based on the concept on **modes**. -Command Mode - vim starts up in this mode, used to navigate and write commands -Insert Mode - used to make changes in your file -Visual Mode - used to highlight text and do operations to them -Ex Mode - used to drop down to the bottom with the ':' prompt to enter commands +- Command Mode - vim starts up in this mode, used to navigate and write commands +- Insert Mode - used to make changes in your file +- Visual Mode - used to highlight text and do operations to them +- Ex Mode - used to drop down to the bottom with the ':' prompt to enter commands ``` i # Puts vim into insert mode, before the cursor position @@ -122,9 +122,9 @@ Ex Mode - used to drop down to the bottom with the ':' prompt to enter comm Vim can be thought of as a set of commands in a 'Verb-Modifier-Noun' format, where: -Verb - your action -Modifier - how you're doing your action -Noun - the object on which your action acts on +- Verb - your action +- Modifier - how you're doing your action +- Noun - the object on which your action acts on A few important examples of 'Verbs', 'Modifiers', and 'Nouns': diff --git a/yaml.html.markdown b/yaml.html.markdown index 8683971e..09c5dfc5 100644 --- a/yaml.html.markdown +++ b/yaml.html.markdown @@ -121,7 +121,7 @@ other_anchor: *anchor_name base: &base name: Everyone has same name -# The regexp << is called Merge Key Language-Independent Type. It is is used to +# The regexp << is called Merge Key Language-Independent Type. It is used to # indicate that all the keys of one or more specified maps should be inserted # into the current map. diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown index deb94cdc..65f125d1 100644 --- a/zh-cn/python-cn.html.markdown +++ b/zh-cn/python-cn.html.markdown @@ -439,7 +439,7 @@ Human.grunt() # => "*grunt*" # 我们可以导入其他模块 import math -print math.sqrt(16) # => 4 +print math.sqrt(16) # => 4.0 # 我们也可以从一个模块中导入特定的函数 from math import ceil, floor diff --git a/zh-cn/solidity-cn.html.markdown b/zh-cn/solidity-cn.html.markdown new file mode 100644 index 00000000..ec684997 --- /dev/null +++ b/zh-cn/solidity-cn.html.markdown @@ -0,0 +1,825 @@ +--- +language: Solidity +filename: learnSolidity-cn.sol +lang: zh-cn +contributors: + - ["Nemil Dalal", "https://www.nemil.com"] + - ["Joseph Chow", ""] + - ["Bhoomtawath Plinsut", "https://github.com/varshard"] + - ["Shooter", "https://github.com/liushooter"] +translators: + - ["Bob Jiang", "https://github.com/bobjiang"] +--- + +Solidity 使你在[以太坊](https://www.ethereum.org/)上编程,一个基于区块链的虚拟机, +允许创建和执行智能合约,无需中心化的或可信的一方。 + +Solidity 是一种与 Javascript 和 C 的相似的、静态类型的合约编程语言。与OOP(面向对象)中 +的对象一样,每个合约都包含状态变量、函数和公共数据类型。合约特定功能包括修饰符(guard)子句, +事件通知的侦听器及自定义的全局变量。 + +以太坊合约的例子包括众筹、投票以及盲拍(私密拍卖)。 + +Solidity 代码中存在高风险和高成本的错误,因此你必须非常小心地进行测试并慢慢地发布。**随着 +以太坊的快速变化,本文档不可能是最新的,所以你应该关注最新的的 solidity 聊天室和以太网博客。 +照搬这里的代码,会存在重大错误或弃用代码模式的风险。(说人话--别照抄例子中的代码)** + +与其他代码不同,可能还需要添加如暂停、弃用和限制使用的设计模式,来降低风险。本文档主要讨论语法, +因此排除了许多流行的设计模式。 + +由于 Solidity 和以太坊正在积极开发,通常会标记为实验或 beta 特性,并很可能会更改。因此欢迎 +提交更改请求。 + +```javascript +// 首先,一个简单的银行合约 +// 允许存款、取款、以及检查余额 + +// simple_bank.sol (注意 .sol 后缀) +/* **** 例子开始 **** */ + +// 声明源文件的编译器版本 +pragma solidity ^0.4.19; + +// 开始 Natspec 注释(三个斜杠) +// 用作文档 - 及UI元素、动作的描述性数据 + +/// @title SimpleBank +/// @author nemild + +/* 'contract' 和其他语言的 'class' 类似 (类变量、继承等) */ +contract SimpleBank { // 单词首字母大写 + // 声明函数外的状态变量,合约生命周期内可用 + + // 地址映射到余额的字典,总是要小心数字的溢出攻击 + mapping (address => uint) private balances; + + // "private" 的意思是其他合约不能直接查询余额,但对于区块链上的其他方来说,数据仍然是可见的。 + + address public owner; + // 'public' 使用户或合约可以从外部读取(不可写) + + // Events(事件) - 向外部监听器发布动作 + event LogDepositMade(address accountAddress, uint amount); + + // Constructor(构造函数)(译者注:solidity 从0.4.22开始使用 constructor() 作为构造函数) + function SimpleBank() public { + // msg 提供了发送给合约的消息详情 + // msg.sender 是合约的调用者(这里是合约创建者的地址) + owner = msg.sender; + } + + /// @notice 存款 ether (以太币) + /// @return 存款后用户的余额 + function deposit() public payable returns (uint) { + // 使用 'require' 来检测用户的输入,'assert' 是内部常量 + // 我们要确保不会发生溢出问题(上溢) + require((balances[msg.sender] + msg.value) >= balances[msg.sender]); + + balances[msg.sender] += msg.value; + // 状态变量不需要 "this." 或 "self." + // 默认情况下,所有值都设置为数据类型的初始值 + + LogDepositMade(msg.sender, msg.value); // 触发事件 + + return balances[msg.sender]; + } + + /// @notice 从银行取款以太币 (ether) + /// @dev 不会返回任何多余的以太币(ether) + /// @param withdrawAmount 取款的数量 + /// @return 用户还剩下的余额 + function withdraw(uint withdrawAmount) public returns (uint remainingBal) { + require(withdrawAmount <= balances[msg.sender]); + + // 注意在发送任何交易,即通过 .transfer .send 调用外部函数之前,马上减掉取款数量 + // 这可以允许调用者使用递归请求大于其余额的金额。目标是在调用外部函数之前提交状态, + // 包括.transfer / .send + balances[msg.sender] -= withdrawAmount; + + // 这会自动引发失败,也就是说还原了更新的余额 + msg.sender.transfer(withdrawAmount); + + return balances[msg.sender]; + } + + /// @notice 获取余额 + /// @return 用户的余额 + // 'view' 防止函数编辑状态变量;允许函数本地运行或链下运行 + function balance() view public returns (uint) { + return balances[msg.sender]; + } +} +// ** 例子结束 ** + + +// 下面, solidity 基础 + +// 1. 数据类型与关联的方法 +// uint 类型用作现金数量(没有双浮点型或单浮点型)及日期(用 unix 时间) +uint x; + +// 256字节的 int, 实例化后不能改变 +int constant a = 8; +int256 constant a = 8; // 和上一行一样,这里256字节显性化了 +uint constant VERSION_ID = 0x123A1; // 16进制常量 +// 'constant' 关键字, 编译器在每个出现的地方替换为实际的值 + +// 所有的状态变量(函数之外的那些),默认是 'internal' 的,只能在合约及所有继承的合约内 +// 可以访问。需要显性的设置为 'public' 才能允许外部合约访问。 +int256 public a = 8; + +// 对于 int 和 uint,可以显性的设置位数(从8位到256位,8位跳跃),如int8, int16, int24 +uint8 b; +int64 c; +uint248 e; + +// 当心不要溢出以及免收此类攻击,例如,对于加法最好这么做: +uint256 c = a + b; +assert(c >= a); // assert 测试内部不变的值;require 用来测试用户输入 +// 更多通用算法问题的例子,参考 Zeppelin's SafeMath library +// https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol + + +// 没有内建的随机函数,使用其他合约获得随机数 + +// 类型转换 +int x = int(b); + +bool b = true; // 或 'var b = true;' 隐含的类型 + +// 地址 - 20个字节或160位以太坊地址(16进制数字),不允许进行运算 +address public owner; + +// 账户类型: +// 合约账户:在创建时设置地址(创建者地址函数,交易发送) +// 外部账户:(个人账户)从公钥创建的地址 + +// 'public' 的含义是自动创建的 getter 方法,而不是 setter 方法可以公开的、外部访问。 + +// 所有地址都可以进行转账 +owner.transfer(SOME_BALANCE); // 失败后还原 + +// 还可以调用较低级别的 .send , 转账失败会返回 false +if (owner.send) {} +// 记住:用 'if' 包着 send 函数,因为合约地址执行这些函数转账时,可能会失败 +// 另外,确保转账前先减掉余额,因为存在递归调用的风险。 + +// 检查余额 +owner.balance; // 所有者的余额(用户或合约) + + +// 字符类型,从1到32位可用 +byte a; // byte 等同于 byte1 +bytes2 b; +bytes32 c; + +// 动态大小的字符 +bytes m; // 特殊的数组,等同于 byte[],比 byte1 到 byte32 更贵 +// 尽可能不用 bytes + +// 等同于 bytes,但不允许长度或索引的访问 +string n = "hello"; // UTF8存储,注意双引号而不是单引号 +// 字符功能未来会增加,推荐使用 bytes32 或 bytes + +// 推断类型 +// var 会根据第一次赋值决定类型,不能用来作为函数的参数 +var a = true; +// 小心使用,推断可能带来错误的类型,例如,int8,而计数器需要的是 int16 + +// 函数可以用 var 类型赋值给变量 +function a(uint x) returns (uint) { + return x * 2; +} +var f = a; +f(22); // 调用 + +// 默认的,所有值实例化后都设为 0 + +// 大多数类型上可以调用删除(不会销毁值,而是设置为0,初始值) +uint x = 5; + + +// 集合 +(x, y) = (2, 7); // 多值的赋值 + + +// 2. 数据结构 +// 数组 +bytes32[5] nicknames; // 静态数组 +bytes32[] names; // 动态数组 +uint newLength = names.push("John"); // 添加返回数组的新长度 +// 长度 +names.length; // 获得数组长度 +names.length = 1; // 可以设定长度(仅针对 storage 中的动态数组) + +// 多维数组 +uint x[][5]; // 5个动态数组元素的数组(和多数语言的顺序相反) + +// 字典类型 (任一类型到其他类型的映射) +mapping (string => uint) public balances; +balances["charles"] = 1; +// balances["ada"]得到 0, 所有没有设定key值的,返回0 +// 'public' 允许跟着(调用)另一份合约 +contractName.balances("charles"); // returns 1 +// 'public' 创建 getter (而不是 setter )如下: +function balances(string _account) returns (uint balance) { + return balances[_account]; +} + +// 内嵌的 mapping +mapping (address => mapping (address => uint)) public custodians; + +// 删除 +delete balances["John"]; +delete balances; // 所有元素设为 0 + +// 不像其他语言,不知道 keys 的话不能列出 mapping 中的所有元素 - 可以在这之上构建数据结构 + +// 结构 +struct Bank { + address owner; + uint balance; +} +Bank b = Bank({ + owner: msg.sender, + balance: 5 +}); +// 或 +Bank c = Bank(msg.sender, 5); + +c.balance = 5; // 设为新值 +delete b; +// 设为初始值,结构内所有变量设为0,除了 mapping + +// 枚举 +enum State { Created, Locked, Inactive }; // 常常作为状态机 +State public state; // 声明枚举变量 +state = State.Created; +// 枚举类型可以显性化的转换为 ints +uint createdState = uint(State.Created); // 0 + +// 数据位置:内存(Memory) vs. 存储(storage) vs. 调用数据(calldata) +// 所有复杂类型(数据、结构)都有一个数据位置,内存数据不持久,而存储的数据是持久的。 +// 本地变量和状态变量默认是存储,函数参数默认是内存。堆栈存放较小的本地变量 + +// 多数类型,可以显性化的设定使用的数据位置 + + +// 3. 简单操作符 +// solidity 提供了比较、位运算及数学运算的功能 +// 指数运算: ** +// 异或运算: ^ +// 按位取反: ~ + + +// 4. 值得注意的全局变量 +// ** this ** +this; // 合约的地址 +// 常常用在合约生命周期结束前,转走剩下的余额 +this.balance; +this.someFunction(); // 通过 call 的方式而不是内部跳转的方式,从外部调用函数 + +// ** msg - 合约收到的当前消息 ** ** +msg.sender; // 发送者的地址 +msg.value; // 该合约内的以太币数量(单位 wei),该函数应该标记为 "payable" +msg.data; // 字符,完整的调用数据 +msg.gas; // 剩余 gas + +// ** tx - 交易信息 ** +tx.origin; // 本次交易的发送者地址 +tx.gasprice; // 本次交易的 gas price + +// ** block - 当前区块信息 ** +now; // 当前时间(大概)block.timestamp的别名 (采用的 Unix 时间) +// 注意这个可能被矿工操纵,因此请小心使用 + +block.number; // 当前区块号 +block.difficulty; // 当前区块难度 +block.blockhash(1); // 返回 bytes32,只对最近 256 个区块有效 +block.gasLimit(); + +// ** 存储 - 持久化存储哈希 ** +storage['abc'] = 'def'; // 256 位单词 到 256 位单词的映射 + + +// 4. 函数及更多 +// A. 函数 +// 简单函数 +function increment(uint x) returns (uint) { + x += 1; + return x; +} + +// 函数可以通过指定返回的参数名,来返回多个参数 +function increment(uint x, uint y) returns (uint x, uint y) { + x += 1; + y += 1; +} +// 调用前一个函数 +uint (a,b) = increment(1,1); + +// 'view' ('constant'的别名) +// 表明函数不会改变持久化的变量,View函数会本地执行,而不是链上运行。 +// 注意:constant 关键字很快会废弃。 +uint y = 1; + +function increment(uint x) view returns (uint x) { + x += 1; + y += 1; // 这一行会失败 + // y 是一个状态变量,不能在 view 的函数里改变 y +} + +// 'pure' 比 'view' 或 'constant' 更加严格,甚至不允许读取状态变量 +// 具体的规则很复杂,请参考 +// view/pure: +// http://solidity.readthedocs.io/en/develop/contracts.html#view-functions + +// '函数可见性指示器' +// 'view'可以有以下修饰符,包括: +// public - 内部及外部可见(函数的默认值) +// external - 仅外部可见(包括 this 发起的调用) +// private - 仅当前合约可见 +// internal - 仅当前合约及继承的合约可见 + +// 通常,显性的标记每个函数是个好主意 + +// 函数的挂起 - 可以将函数赋值给变量 +function a() { + var z = b; + b(); +} + +function b() { + +} + +// 所有接收 ether 的函数必须标记为 'payable' +function depositEther() public payable { + balances[msg.sender] += msg.value; +} + + +// 首选循环来递归(最大的调用堆栈深度是 1024),另外不要设置没有限制的循环, +// 因为这可能会达到 gas limit + +// B. 事件 +// 事件通知外部各方; 易于搜索和访问来自外部区块链(使用轻客户端)的事件 +// 通常在合约参数之后声明 + +// 通常,首字母大写并在前面加上 Log ,防止与函数混淆 + +// 声明 +event LogSent(address indexed from, address indexed to, uint amount); // 注意 capital first letter + +// 调用 +LogSent(from, to, amount); + +/* + // 对于外部方(合约或外部实体),使用 Web3 Javascript 库来监听 + // 以下是javascript代码,不是solidity代码 + Coin.LogSent().watch({}, '', function(error, result) { + if (!error) { + console.log("Coin transfer: " + result.args.amount + + " coins were sent from " + result.args.from + + " to " + result.args.to + "."); + console.log("Balances now:\n" + + "Sender: " + Coin.balances.call(result.args.from) + + "Receiver: " + Coin.balances.call(result.args.to)); + } + } + +*/ + +// 一个合约依赖另一个合约的共同范例(例如,合约取决于另一个合约提供的当前汇率) + +// C. 修饰器 +// 修饰器验证函数的输入,例如最小余额或用户身份验证; 类似于其他语言的保护子句 + +// '_' (下划线)经常用在代码的最后一行,表明被调用的函数放在那里 +modifier onlyAfter(uint _time) { require (now >= _time); _; } +modifier onlyOwner { require(msg.sender == owner) _; } +// 常用于状态机 +modifier onlyIfStateA (State currState) { require(currState == State.A) _; } + +// 修饰器紧跟在函数声明之后 +function changeOwner(newOwner) +onlyAfter(someTime) +onlyOwner() +onlyIfState(State.A) +{ + owner = newOwner; +} + +// 下划线可以包含在代码结束之前,但明显地返回将跳过后面的代码,因此谨慎使用 +modifier checkValue(uint amount) { + _; + if (msg.value > amount) { + uint amountToRefund = amount - msg.value; + msg.sender.transfer(amountToRefund); + } +} + + +// 6. 判断和循环 + +// 所有基本的逻辑判断都有效 - 包括 if else, for, while, break, continue +// return - 但不跳转 + +// 语法同 javascript, 但没有从非布尔值到布尔值的类型转换 +// (必须使用比较操作符获得布尔变量值) + +// 请注意由用户行为决定的循环 - 因为合约对于代码块具有最大量的 gas 限制 - +// 如果超过限制该代码则将失败 +// 例如: +for(uint x = 0; x < refundAddressList.length; x++) { + refundAddressList[x].transfer(SOME_AMOUNT); +} + +// 上述两个错误: +// 1. 转账失败会阻塞循环完成,钱被占用 +// 2. 该循环可能会很长(根据需要赔偿的用户数量而定),并且也可能由于超过一个区块最大 gas 限制 +// 而总是失败。你应该让人们自己从他们的子账户取款并标记取款完成 +// 例如,首选拉动式的付款,而不是推动式的付款 + + +// 7. 对象与合约 + +// A. 调用外部合约 +contract InfoFeed { + function info() returns (uint ret) { return 42; } +} + +contract Consumer { + InfoFeed feed; // 指向区块链上的一个合约 + + // 设置 feed 为已存在的合约实例 + function setFeed(address addr) { + // 当心类型自动转换;不会调用构造函数 + feed = InfoFeed(addr); + } + + // 设置 feed 为一个合约的新实例 + function createNewFeed() { + feed = new InfoFeed(); // 创建新实例,调用构造函数 + } + + function callFeed() { + // 最后的括号调用合约,可选择的增加自定义的 ether 或 gas 价格 + feed.info.value(10).gas(800)(); + } +} + +// B. 继承 + +// 和顺序有关,最后继承的合约(如 'def')可以覆盖之前已继承合约的部分 +contract MyContract is abc, def("a custom argument to def") { + +// 覆盖函数 + function z() { + if (msg.sender == owner) { + def.z(); // 调用覆盖的函数 + super.z(); // 调用继承的上层合约的函数 + } + } +} + +// 抽象函数 +function someAbstractFunction(uint x); +// 不可以编译,因此用在基础或抽象合约中,等待实现 + +// C. 导入 + +import "filename"; +import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol"; + + +// 8. 其他关键字 + +// A. 自毁 +// 自毁当前的合约,转账资金到一个地址(常常是创建者的地址) +selfdestruct(SOME_ADDRESS); + +// 从当前或以后的区块中移除存储或代码,会帮助客户端瘦身,但之前的数据会永久在区块链中 + +// 常见模式,让所有者结束合约并收回剩余的资金 +function remove() { + if(msg.sender == creator) { // 只有合约的创建者可以这么做 + selfdestruct(creator); // 自毁合约,返还资金 + } +} + +// 可能希望手动停用合约,而不是自毁 +// (发送到自毁合约的 ether 会丢失掉) + + +// 9. 注意合约的设计 + +// A. 困惑 +// 区块链上所有变量都是公开可见的,因此任何私有的需求变得很困惑。(好比哈希的秘密) + +// 步骤: 1. 承诺某事, 2. 揭示承诺 +keccak256("some_bid_amount", "some secret"); // commit + +// 以后调用合约的 reveal 函数,展示出用 SHA3 哈希的 bid 加 secret +reveal(100, "mySecret"); + +// B. 存储优化 +// 写入区块链可能很昂贵,因为数据是永久存储的;鼓励用巧妙的方法使用内存 +//(最终,编译会更好,但现在有利于规划数据结构 - 并将最小数量存储在区块链中) + +// 多维数组这样的变量可能会成本很高 +// (成本用于存储数据 - 而不是声明未填充的变量) + +// C. 区块链中的数据访问 +// 不能限制人或计算机读取交易或交易状态的内容 + +// 然而 'private' 可以防止其他*合约*直接读取数据 - 任意其他方仍然可以从区块链读取数据 + +// 从开始的所有数据都存在区块链上,因此任何人都可以查看之前的所有数据和变化 + +// D. 定时任务 +// 必须手动调用合约来处理时间相关的调度;也可以创建外部代码来定期的ping, +// 或为其他人提供激励(以太) + +// E. 观察者模式 +//观察者模式允许您注册为订阅者,然后注册一个由oracle调用的函数 +//(注意,oracle 需要付费来运行此操作)。与 Pub / sub 中的订阅有些相似之处 + +// 这是一个抽象合约,包括客户端和服务器端的类的导入,客户端应该要实现 +contract SomeOracleCallback { + function oracleCallback(int _value, uint _time, bytes32 info) external; +} + +contract SomeOracle { + SomeOracleCallback[] callbacks; // 所有订阅者的数组 + + // 注册订阅者 + function addSubscriber(SomeOracleCallback a) { + callbacks.push(a); + } + + function notify(value, time, info) private { + for(uint i = 0;i < callbacks.length; i++) { + // 所有调用的订阅者必须实现 oracleCallback + callbacks[i].oracleCallback(value, time, info); + } + } + + function doSomething() public { + // 实现的代码 + + // 通知所有的订阅者 + notify(_value, _time, _info); + } +} + +// 现在你的客户端合约可以通过 importing SomeOracleCallback 和注册某些 Oracle 来 +// addSubscriber 添加订阅者 + +// F. 状态机 +// 参见如下的例子,枚举类型的 State 和 修饰器 inState + + +// *** 例子: 众筹的例子(与 Kickstarter 大致相似)*** +// ** 开始例子 ** + +// CrowdFunder.sol +pragma solidity ^0.4.19; + +/// @title CrowdFunder +/// @author nemild +/// @translator bobjiang +contract CrowdFunder { + // 由创建者创建的变量 + address public creator; + address public fundRecipient; // 创建者可能和收件人不同 + uint public minimumToRaise; // 需要提示,否则每个人都会得到退款 + string campaignUrl; + byte constant version = 1; + + // 数据结构 + enum State { + Fundraising, + ExpiredRefund, + Successful + } + struct Contribution { + uint amount; + address contributor; + } + + // 状态变量State variables + State public state = State.Fundraising; // 创建时实例化 + uint public totalRaised; + uint public raiseBy; + uint public completeAt; + Contribution[] contributions; + + event LogFundingReceived(address addr, uint amount, uint currentTotal); + event LogWinnerPaid(address winnerAddress); + + modifier inState(State _state) { + require(state == _state); + _; + } + + modifier isCreator() { + require(msg.sender == creator); + _; + } + + // 允许合约销毁之前,最终合约状态后要等待24周 + modifier atEndOfLifecycle() { + require(((state == State.ExpiredRefund || state == State.Successful) && + completeAt + 24 weeks < now)); + _; + } + + function CrowdFunder( + uint timeInHoursForFundraising, + string _campaignUrl, + address _fundRecipient, + uint _minimumToRaise) + public + { + creator = msg.sender; + fundRecipient = _fundRecipient; + campaignUrl = _campaignUrl; + minimumToRaise = _minimumToRaise; + raiseBy = now + (timeInHoursForFundraising * 1 hours); + } + + function contribute() + public + payable + inState(State.Fundraising) + returns(uint256 id) + { + contributions.push( + Contribution({ + amount: msg.value, + contributor: msg.sender + }) // 采用数组,因此可以遍历 + ); + totalRaised += msg.value; + + LogFundingReceived(msg.sender, msg.value, totalRaised); + + checkIfFundingCompleteOrExpired(); + return contributions.length - 1; // 返回 id + } + + function checkIfFundingCompleteOrExpired() + public + { + if (totalRaised > minimumToRaise) { + state = State.Successful; + payOut(); + + // 可以激励在这里发起状态改变的人 + } else if ( now > raiseBy ) { + state = State.ExpiredRefund; // 支持者可以通过调用 getRefund(id) 收取退款 + } + completeAt = now; + } + + function payOut() + public + inState(State.Successful) + { + fundRecipient.transfer(this.balance); + LogWinnerPaid(fundRecipient); + } + + function getRefund(uint256 id) + inState(State.ExpiredRefund) + public + returns(bool) + { + require(contributions.length > id && id >= 0 && contributions[id].amount != 0 ); + + uint256 amountToRefund = contributions[id].amount; + contributions[id].amount = 0; + + contributions[id].contributor.transfer(amountToRefund); + + return true; + } + + function removeContract() + public + isCreator() + atEndOfLifecycle() + { + selfdestruct(msg.sender); + // 创建者获得所有未被声明的钱 + } +} +// ** 结束例子 ** + +// 10. 其他原生的函数 + +// 货币单位 +// 货币使用 wei 来定义,以太币的最小单位 = 1 wei; +uint minAmount = 1 wei; +uint a = 1 finney; // 1 ether == 1000 finney +// 其他单位,请参阅: http://ether.fund/tool/converter + +// 时间单位 +1 == 1 second +1 minutes == 60 seconds + +// 可以乘以带时间单位的变量,因为单位不会存储在变量中 +uint x = 5; +(x * 1 days); // 5 天 + +// 小心闰秒闰年与平等声明的时间 +// (相反,首选大于或小于) + +// 加密算法 +// 传递的所有字符串在哈希操作之前需要连接在一起 +sha3("ab", "cd"); +ripemd160("abc"); +sha256("def"); + +// 11. 安全 + +// 以太坊的合约中,错误可能是灾难性的 - 即使在 solidity 中是流行的模式,也可能发现是反模式的 + +// 参见文档底部的安全链接 + +// 12. 较低层次的函数 +// call - 较低层次,不会经常使用,不提供类型安全性 +successBoolean = someContractAddress.call('function_name', 'arg1', 'arg2'); + +// callcode - 在调用合约的*上下文*中执行的目标地址上的代码 +// 提供库功能 +someContractAddress.callcode('function_name'); + + +// 13. 注意风格 +// 基于 Python 的 PEP8 风格指南 +// 全部风格指南: http://solidity.readthedocs.io/en/develop/style-guide.html + +// 快速总结: +// 4个空格缩进 +// 两行隔开合约声明(和其他高级别的声明) +// 避免括号内留出多余的空格 +// 可以省略一行语句的花括号 (if, for, 等) +// else 应该单独一行 + + +// 14. NATSPEC 注释 +// 用于文档、注释和外部UI + +// 合约的 natspec - 总是在合约定义的上面 +/// @title 合约标题 +/// @author 作者名字 + +// 函数的 natspec +/// @notice 函数做什么的相关信息;展示什么时候执行该函数、 +/// @dev 开发者使用的函数文档 + +// 函数参数、返回值的 natspec +/// @param 有关参数用途的描述 +/// @return 返回值的描述 +``` + +## 更多资源 +- [Solidity Docs](https://solidity.readthedocs.org/en/latest/) +- [Smart Contract Best Practices](https://github.com/ConsenSys/smart-contract-best-practices) +- [EthFiddle - The JsFiddle for Solidity](https://ethfiddle.com/) +- [Browser-based Solidity Editor](https://remix.ethereum.org/) +- [Gitter Solidity Chat room](https://gitter.im/ethereum/solidity) +- [Modular design strategies for Ethereum Contracts](https://docs.erisindustries.com/tutorials/solidity/) + +## 重要的库文件 +- [Zeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/): Libraries that provide common contract patterns (crowdfuding, safemath, etc) + +## 示例合约 +- [Dapp Bin](https://github.com/ethereum/dapp-bin) +- [Solidity Baby Step Contracts](https://github.com/fivedogit/solidity-baby-steps/tree/master/contracts) +- [ConsenSys Contracts](https://github.com/ConsenSys/dapp-store-contracts) +- [State of Dapps](http://dapps.ethercasts.com/) + +## 安全 +- [Thinking About Smart Contract Security](https://blog.ethereum.org/2016/06/19/thinking-smart-contract-security/) +- [Smart Contract Security](https://blog.ethereum.org/2016/06/10/smart-contract-security/) +- [Hacking Distributed Blog](http://hackingdistributed.com/) + +## 风格 +- [Solidity Style Guide](http://solidity.readthedocs.io/en/latest/style-guide.html): Ethereum's style guide is heavily derived from Python's [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide. + +## 编辑器 +- [Emacs Solidity Mode](https://github.com/ethereum/emacs-solidity) +- [Vim Solidity](https://github.com/tomlion/vim-solidity) +- Editor Snippets ([Ultisnips format](https://gist.github.com/nemild/98343ce6b16b747788bc)) + +## Future to Dos +- 新关键字: protected, inheritable +- 常见设计模式列表 (throttling, RNG, version upgrade) +- 常见的安全反模式 + +请随意发送 pull request 或者发邮件给作者 nemild -/at-/ gmail + +或者发邮件给译者 jiangxb -/at-/ gmail.com diff --git a/zh-tw/python-tw.html.markdown b/zh-tw/python-tw.html.markdown index 553181d8..cd7481d7 100644 --- a/zh-tw/python-tw.html.markdown +++ b/zh-tw/python-tw.html.markdown @@ -627,7 +627,7 @@ i.age # => raises an AttributeError # 你可以引入模組來做使用 import math -print math.sqrt(16) # => 4 +print math.sqrt(16) # => 4.0 # math.sqrt()為取根號 # 你可以只從模組取出特定幾個函式 |