একটি প্রোগ্রামিং ভাষা যা আপনাকে সাধারণ ধরণের জন্য নতুন সীমা নির্ধারণ করতে দেয়


19

অনেক ভাষায় পছন্দ C++, C#এবং Javaআপনি যে বস্তু মত সহজ ধরনের প্রতিনিধিত্ব তৈরি করার অনুমতি দেয় integerবা float। ক্লাস ইন্টারফেস ব্যবহার করে আপনি অপারেটরদের ওভাররাইড করতে পারেন এবং মানটি 100 এর ব্যবসায়িক বিধি ছাড়িয়ে যায় কিনা তা পরীক্ষা করার মতো যুক্তি সম্পাদন করতে পারেন।

আমি ভাবছি কিছু ভাষায় এই নিয়মগুলিকে কোনও পরিবর্তনশীল / সম্পত্তির টিকা বা বৈশিষ্ট্য হিসাবে সংজ্ঞায়িত করা সম্ভব কিনা।

উদাহরণস্বরূপ, C#আপনি লিখতে পারেন:

[Range(0,100)]
public int Price { get; set; }

অথবা হতে C++পারে আপনি লিখতে পারে:

int(0,100) x = 0;

আমি এর আগে এমন কিছু কখনও দেখিনি, তবে সঞ্চয় করার আগে আমরা ডেটা বৈধতার উপর কতটা নির্ভরশীল হয়েছি তা দেওয়া হয়েছে। এটি আশ্চর্যজনক যে এই বৈশিষ্ট্যটি ভাষাগুলিতে যুক্ত করা হয়নি।

আপনি যেখানে ভাষাগুলির উদাহরণ দিতে পারেন যেখানে এটি সম্ভব?


14
আদা কি এমন কিছু না?
zxcdw

2
@zxcdw: হ্যাঁ, অ্যাডা প্রথম ভাষা ছিল (যেমন আমি জানি) যা এই জাতীয় "প্রকার" এর সমর্থনে তৈরি করেছে। সীমাবদ্ধ ডেটা প্রকারের নামকরণ।
m0nhakk

4
নির্ভরশীলভাবে টাইপ করা সমস্ত ভাষাতে এই ক্ষমতা থাকবে। এটি প্রকৃতপক্ষে প্রকৃতির প্রকৃতির যেমন এন.ইউইকিপিডিয়া.আর / উইকি / ডিপেন্ডেন্ট_ টাইপ যদিও আপনি যে কোনও এমএলে এই স্বভাবের একটি নিজস্ব প্রকার তৈরি করতে পারেন, এই ভাষাগুলিতে একটি ধরণের সংজ্ঞা দেওয়া হয়েছে data Bool = True | Falseএবং আপনি যা বলতে চান তার জন্য data Cents = 0 | 1 | 2 | ...একটি থাকতে পারে "বীজগণিত ডেটা টাইপগুলি" দেখুন (যা হ্যান্ডলি-মিলনার ধরণের নামকরণের আরও বেশি হওয়া উচিত তবে লোকে বিরক্তিকরভাবে অনুমানের সাথে বিভ্রান্ত করে) en.wikedia.org/wiki/Algebraic_data_type
জিমি হোফা

2
আপনার নাম দেওয়া ভাষাগুলি কীভাবে পূর্ণসংখ্যাকে ওভার-ও আন্ডারফ্লো হ্যান্ডেল করে তা প্রদত্ত, আপনি যদি নীরবটিকে ওভারফ্রোভ / আন্ডারফ্লোতে রাখেন তবে তার নিজের পক্ষে এ জাতীয় পরিসীমা নিষেধাজ্ঞার পক্ষে খুব বেশি মূল্য হবে না।

9
@ স্টিভেনবার্নাপ: প্রকারের জন্য ওও প্রয়োজন হয় না। typeসর্বোপরি পাস্কালে একটি কীওয়ার্ড রয়েছে। প্রোগ্রামিং ভাষাগুলির "অটোমার" বৈশিষ্ট্যের চেয়ে অবজেক্ট ওরিয়েন্টেশন হ'ল ডিজাইন প্যাটার্ন।
ভাইরবল

উত্তর:


26

পাস্কলের সাবরাজ্যের ধরণ ছিল, অর্থাত্ একটি ভেরিয়েবলের সাথে মানিয়ে যাওয়া সংখ্যার সংখ্যা হ্রাস।

  TYPE name = val_min .. val_max;

অ্যাডাও রেঞ্জগুলির একটি ধারণা রয়েছে: http://en.wikibooks.org/wiki/Ada_Programming/Typees/range

উইকিপিডিয়া থেকে ....

type Day_type   is range    1 ..   31;
type Month_type is range    1 ..   12;
type Year_type  is range 1800 .. 2100;
type Hours is mod 24;
type Weekday is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); 

করতে পারে

subtype Weekend is  Weekday (Saturday..Sunday);
subtype WorkDay is  Weekday (Monday..Friday);

এবং এটি এখানে দুর্দান্ত হয়

year : Year_type := Year_type`First -- 1800 in this case...... 

সি এর কঠোর সাবঞ্জ্রে টাইপ নেই তবে ব্যবহৃত বিটের সংখ্যা হ্রাস করতে বিটফিল্ড ব্যবহার করে একটি (নূন্যতম সীমাবদ্ধ) নকল করার উপায় রয়েছে। struct {int a : 10;} my_subrange_var;}। এটি ভেরিয়েবল কন্টেন্টের জন্য উপরের সীমানা হিসাবে কাজ করতে পারে (সাধারণভাবে আমি বলব: এর জন্য বিটফিল্ড ব্যবহার করবেন না , এটি কেবলমাত্র একটি বিন্দু প্রমাণের জন্য)।

অন্যান্য ভাষায় যথেচ্ছ দৈর্ঘ্যের পূর্ণসংখ্যার ধরণের জন্য প্রচুর সমাধান লাইব্রেরি-স্তরে ঘটে থাকে, আই সি ++ টেমপ্লেট ভিত্তিক সমাধানের জন্য মঞ্জুরি দেয়।

এমন ভাষাগুলি রয়েছে যা পরিবর্তনশীল রাজ্যগুলির নিরীক্ষণ এবং এর সাথে সংযুক্তি যুক্ত করার অনুমতি দেয়। উদাহরণস্বরূপ Clojurescript এ

(defn mytest 
   [new-val] 
   (and (< new-val 10)
        (<= 0 new-val)))

(def A (atom 0 :validator mytest))

শর্ত পূরণ হয়েছে কিনা তা পরীক্ষা করে (মাধ্যমে বা ) পরিবর্তন করা mytestহলে ফাংশনটি ডাকা হয়। দেরী-বাঁধাই করা ভাষাগুলিতে সাব্রিজ আচরণ বাস্তবায়নের জন্য এটি উদাহরণ হতে পারে (দেখুন http://blog.fogus.me/2011/09/23/clojurescript-watchers-and-uthorators/ )।areset!swap!


2
আপনি যদি নির্ভরশীল প্রকারগুলি সম্পর্কেও বিশদ যুক্ত করেন তবে ভাল লাগবে, এই সমস্যাটি নির্ভর নির্ভর টাইপিংয়ের পুরো উদ্দেশ্য এবং কারণ, মনে হয় এটি কমপক্ষে উল্লেখ করা উচিত (এমনকি এটি রহস্যজনক হলেও)
জিমি হোফা

যদিও নির্ভরশীল ধরণের এবং ইন্ডাকটিভ যুক্তি / মিলার-টাইপ অনুমান সম্পর্কে আমার কিছুটা বোধগম্যতা রয়েছে। আমি যারা তাদের সাথে অনুশীলন খুব কম। আপনি যদি আমার উত্তরে তথ্য যুক্ত করতে চান তবে এটি সম্পাদনা করতে নির্দ্বিধায়। আমি অনুপ্রেরণামূলক সংজ্ঞা দিয়ে গণিতে পিয়ানো অ্যাক্সিওমস এবং সংখ্যা ধরণের সম্পর্কে কিছু যুক্ত করতে যাচ্ছিলাম তবে একটি ভাল এমএল ডেটা উদাহরণ সম্ভবত আরও সার্থক হতে পারে।
ভাইরবল

আপনি এনাম ব্যবহার করে সি-তে একটি পরিসরের ধরণটি পোড়াতে পারেন
জন কার্টরাইট

1
এনাম টাইপ ইন্ট বা স্বাক্ষরবিহীন ইনট (আফ্রিকান টাইপ) (আমার মনে হয় এটি সংকলক নির্দিষ্ট) এবং আবদ্ধ-পরীক্ষিত নয়।
1313

এটি তার থেকে আরও শীতল হয়ে যায়: বিন্যাসিত ধরণেরগুলি অ্যারে ঘোষণায় এবং for y in Year_Type loop ... বাফার ওভারফ্লোগুলির মতো সমস্যাগুলি দূর করার জন্য লুপগুলির জন্য ব্যবহার করা যেতে পারে ।
ব্রায়ান ড্রামন্ড

8

অ্যাডা এমন একটি ভাষা যা সাধারণ প্রকারের সীমাবদ্ধতা দেয়, প্রকৃতপক্ষে এডায় আপনার প্রোগ্রামটির সঠিকতার গ্যারান্টি দেওয়ার জন্য আপনার নিজস্ব ধরণের সংজ্ঞা দেওয়া ভাল অভ্যাস ।

type MyType1   is range    1 .. 100;
type MyType2   is range    5 .. 15;

myVar1 : MyType1;

এটি ডিওডি দ্বারা দীর্ঘ সময় ব্যবহার করা হয়েছিল, সম্ভবত এখনও রয়েছে তবে আমি এর বর্তমান ব্যবহারের ট্র্যাক হারিয়ে ফেলেছি।


2
সুরক্ষা সমালোচনামূলক সিস্টেমে অ্যাডা এখনও বহুল ব্যবহৃত। নির্ভরযোগ্য এবং রক্ষণাবেক্ষণযোগ্য সফ্টওয়্যার লেখার জন্য ভাষাটিকে আজকের সময়ের মধ্যে একটি সেরা উপলব্ধ হয়ে ওঠার জন্য একটি সাম্প্রতিক আপডেট রয়েছে। দুর্ভাগ্যক্রমে সরঞ্জাম সমর্থন (সংকলক, আইডিই টেস্ট ফ্রেমওয়ার্ক ইত্যাদি) ব্যয়বহুল এবং এর সাথে কাজ করা শক্ত এবং অনুৎপরমূলক করে তুলতে পিছিয়ে রয়েছে।
mattnz

লজ্জাজনক, আমি এটি প্রথমবারের মতো ব্যবহার করার কথা মনে করি এবং এতে কোডটি কীভাবে পরিষ্কার এবং ত্রুটিমুক্ত করা যায় তা অবাক করেছিলাম। এটি এখনও সক্রিয়ভাবে আপডেট হওয়া, এখনও একটি দুর্দান্ত ভাষা শুনে খুশী।
লোভীবন্ধ

@ ম্যাট্টনজ: জিএনএটি জিসিসি স্যুটের একটি অংশ, এবং এটি বিনামূল্যে এবং বেতনের উভয় সংস্করণে বিদ্যমান।
কিথ থম্পসন

@ কিথ: জিএনএটি সংকলক বিনামূল্যে। আইডিই এবং ফ্রেমওয়ার্কগুলি এখনও ব্যয়বহুল এবং কার্যকারিতার অভাব।
mattnz

7

সি ++ এ কীভাবে একটি সীমা-চেক করা মান প্রকার তৈরি করতে হয় তার উদাহরণের জন্য সি ++ তে মান ধরণের সীমাবদ্ধতা দেখুন ।

এক্সিকিউটিভ সংক্ষিপ্তসার: অন্তর্নির্মিত সর্বনিম্ন এবং সর্বাধিক মান রয়েছে এমন একটি মান প্রকার তৈরি করতে একটি টেম্পলেট ব্যবহার করুন, যা আপনি এটির মতো ব্যবহার করতে পারেন:

// create a float named 'percent' that's limited to the range 0..100
RangeCheckedValue<float, 0, 100> percent(50.0);

আপনার এখানে সত্যিকারের কোনও টেম্পলেট দরকার নেই; আপনি অনুরূপ প্রভাব একটি বর্গ ব্যবহার করতে পারে। একটি টেমপ্লেট ব্যবহার আপনাকে অন্তর্নিহিত ধরণ নির্দিষ্ট করতে দেয়। এছাড়াও, এটি লক্ষ্য করাও গুরুত্বপূর্ণ যে percentউপরের floatধরণটি কোনওটি নয়, বরং টেমপ্লেটের উদাহরণ হবে। এটি আপনার প্রশ্নের 'সাধারণ প্রকারের' দিকটি সন্তুষ্ট করতে পারে না।

এটি আশ্চর্যজনক যে এই বৈশিষ্ট্যটি ভাষাগুলিতে যুক্ত করা হয়নি।

সাধারণ প্রকারগুলি কেবল এটিই - সহজ। সরাসরি ব্যবহার না করে আপনার প্রয়োজনীয় সরঞ্জামগুলি তৈরি করার জন্য এগুলি প্রায়শই বিল্ডিং ব্লক হিসাবে ব্যবহার করা হয়।


2
@ জিমিহোফা আমার ধারনা করার মতো এমন কয়েকটি ক্ষেত্রে রয়েছে যে সংকলকটি পরিসরের শর্তগুলির বাইরে সনাক্ত করতে পারে, রেঞ্জ চেকিং বেশিরভাগ রান টাইমে হওয়া দরকার। সংকলক সম্ভবত তা জানতে পারে না যে আপনি ওয়েব সার্ভার থেকে ডাউনলোড করা মানটি সীমার মধ্যে থাকবে কিনা, বা ব্যবহারকারী কোনও তালিকায় একাধিক রেকর্ড যুক্ত করবেন কিনা বা যাই হোক না কেন।
কালেব

7

আপনার লক্ষ্যের কিছু সীমাবদ্ধ রূপটি টীকা এবং ডায়নামিক প্রক্সি প্যাটার্নের সংমিশ্রণের মাধ্যমে জাভা এবং সি # তে আমার জ্ঞানের পক্ষে সম্ভব (জাভা এবং সি # তে গতিশীল প্রক্সিগুলির জন্য অন্তর্নির্মিত বাস্তবায়ন রয়েছে)।

জাভা সংস্করণ

টিকা:

@Target(ElementType.PARAMETER)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface IntRange {
     int min ();
     int max ();
}

প্রকৃতির দৃষ্টান্ত তৈরি করে র‌্যাপার শ্রেণি:

public class Wrapper {
    public static Object wrap(Object obj) {
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new MyInvocationHandler(obj));
    }
}

ইনভোকেশনহ্যান্ডলার প্রতিটি পদ্ধতি কলটিতে বাইপাস হিসাবে পরিবেশন করছেন:

public class MyInvocationHandler implements InvocationHandler {
    private Object impl;

    public MyInvocationHandler(Object obj) {
        this.impl = obj;
    }

@Override
public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
    Annotation[][] parAnnotations = method.getParameterAnnotations();
    Annotation[] par = null;
    for (int i = 0; i<parAnnotations.length; i++) {
        par = parAnnotations[i];
        if (par.length > 0) {
            for (Annotation anno : par) {
                if (anno.annotationType() == IntRange.class) {
                    IntRange range = ((IntRange) anno);
                    if ((int)args[i] < range.min() || (int)args[i] > range.max()) {
                        throw new Throwable("int-Parameter "+(i+1)+" in method \""+method.getName()+"\" must be in Range ("+range.min()+","+range.max()+")"); 
                    }
                }
            }
        }
    }
    return method.invoke(impl, args);
}
}

ব্যবহারের জন্য উদাহরণ-ইন্টারফেস:

public interface Example {
    public void print(@IntRange(min=0,max=100) int num);
}

প্রধান-পদ্ধতি:

Example e = new Example() {
    @Override
    public void print(int num) {
        System.out.println(num);
    }
};
e = (Example)Wrapper.wrap(e);
e.print(-1);
e.print(10);

আউটপুট:

Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy0.print(Unknown Source)
at application.Main.main(Main.java:13)
Caused by: java.lang.Throwable: int-Parameter 1 in method "print" must be in Range (0,100)
at application.MyInvocationHandler.invoke(MyInvocationHandler.java:27)
... 2 more

সি শার্প -Version

টীকাগুলি (সি # তে বৈশিষ্ট্য বলে):

[AttributeUsage(AttributeTargets.Parameter)]
public class IntRange : Attribute
{
    public IntRange(int min, int max)
    {
        Min = min;
        Max = max;
    }

    public virtual int Min { get; private set; }

    public virtual int Max { get; private set; }
}

ডায়নামিকবজেক্ট সাব-ক্লাস:

public class DynamicProxy : DynamicObject
{
    readonly object _target;

    public DynamicProxy(object target)
    {
        _target = target;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        TypeInfo clazz = (TypeInfo) _target.GetType();
        MethodInfo method = clazz.GetDeclaredMethod(binder.Name);
        ParameterInfo[] paramInfo = method.GetParameters();
        for (int i = 0; i < paramInfo.Count(); i++)
        {
            IEnumerable<Attribute> attributes = paramInfo[i].GetCustomAttributes();
            foreach (Attribute attr in attributes)
            {
                if (attr is IntRange)
                {
                    IntRange range = attr as IntRange;
                    if ((int) args[i] < range.Min || (int) args[i] > range.Max)
                        throw new AccessViolationException("int-Parameter " + (i+1) + " in method \"" + method.Name + "\" must be in Range (" + range.Min + "," + range.Max + ")");
                }
            }
        }

        result = _target.GetType().InvokeMember(binder.Name, BindingFlags.InvokeMethod, null, _target, args);

        return true;
    }
}

দ্য দ্য ক্লাস:

public class ExampleClass
{
    public void PrintNum([IntRange(0,100)] int num)
    {
        Console.WriteLine(num.ToString());
    }
}

ব্যবহার:

    static void Main(string[] args)
    {
        dynamic myObj = new DynamicProxy(new ExampleClass());
        myObj.PrintNum(99);
        myObj.PrintNum(-5);
    }

উপসংহারে, আপনি দেখতে পাচ্ছেন যে জাভাতে কাজ করার জন্য আপনি এরকম কিছু পেতে পারেন , তবে এটি পুরোপুরি সুবিধাজনক নয়, কারণ

  • প্রক্সি ক্লাসটি কেবল ইন্টারফেসের জন্য ইনস্ট্যান্ট করা যায়, অর্থাত আপনার ক্লাসটি একটি ইন্টারফেস প্রয়োগ করতে হবে
  • অনুমোদিত রেঞ্জটি কেবলমাত্র ইন্টারফেস স্তরে ঘোষণা করা যেতে পারে
  • পরে ব্যবহার শুরুতে অতিরিক্ত প্রচেষ্টা সহ আসে (MyInvocationHandler, প্রতিটি ইনস্ট্যান্টে মোড়ানো) যা সামান্য বোধগম্যতাও হ্রাস করে

সি # তে ডায়নামিকবজেক্ট শ্রেণীর ক্ষমতা ইন্টারফেসের সীমাবদ্ধতা সরিয়ে দেয়, যেমন আপনি সি # বাস্তবায়নে দেখছেন। দুর্ভাগ্যক্রমে, এই গতিশীল আচরণটি এক্ষেত্রে স্থিতিশীল ধরণের সুরক্ষা অপসারণ করে, তাই গতিশীল প্রক্সিটিতে কোনও পদ্ধতিতে কল অনুমোদিত কিনা তা নির্ধারণ করার জন্য রানটাইম চেকগুলি প্রয়োজনীয়।

যদি এই বিধিনিষেধগুলি আপনার পক্ষে গ্রহণযোগ্য হয়, তবে এটি আরও খননের জন্য ভিত্তি হিসাবে কাজ করতে পারে!


1
ধন্যবাদ, এটি একটি দুর্দান্ত উত্তর। সি # তে কি এরকম কিছু সম্ভব?
প্রতিক্রিয়াশীল

1
সবেমাত্র একটি নমুনা সি # বাস্তবায়ন যুক্ত করা হয়েছে!
ম্যাকম্যানাস

শুধু অবগতির জন্য: public virtual int Min { get; private set; }একটা চমৎকার কৌতুক যে আপনার কোড উল্লেখযোগ্যভাবে কমান হবে
ড্যানি Pflughoeft - BlueRaja

2
এটি কিউ এর থেকে সম্পূর্ণ আলাদা, কারণ আপনি যা করছেন তা মূলত গতিশীলতা; যা টাইপিংয়ের বিরোধী যেখানে এই প্রশ্নটি একটি টাইপের জন্য জিজ্ঞাসা করছে , পার্থক্যটি যখন টাইপটিতে থাকে তখন এটি রান-টাইম নয় সংকলন সময়ে প্রয়োগ করা হয়। রান সময়ে রেঞ্জগুলি কীভাবে বৈধ করা যায় সে সম্পর্কে কেউ জিজ্ঞাসা করেনি, তিনি টাইপ সিস্টেমটি যা সংকলনের সময় পরীক্ষা করা হয় তার দ্বারা এটি বৈধতা চেয়েছিল।
জিমি হোফা

1
পছন্দ করেছেন শুভ পয়েন্ট :)
সংঘটিত

2

রেঞ্জগুলি হানাদারদের একটি বিশেষ ক্ষেত্রে। উইকিপিডিয়া থেকে:

একটি আক্রমণকারী হ'ল একটি শর্ত যা কোনও প্রোগ্রাম কার্যকর করার সময় সত্য হতে পারে।

আক্রমণকারী x> = a এবং x <= b এর সাথে একটি পরিসীমা প্রকারের [a, b]পরিবর্তনশীল x হিসাবে ঘোষিত হতে পারে ।Integer

অতএব অ্যাডা বা পাস্কাল সাবঞ্জ্রে প্রকারগুলি কঠোরভাবে প্রয়োজনীয় নয়। তারা আক্রমণকারীদের সাথে একটি পূর্ণসংখ্যার ধরণের মাধ্যমে প্রয়োগ করা যেতে পারে।


0

এটি আশ্চর্যজনক যে এই বৈশিষ্ট্যটি ভাষাগুলিতে যুক্ত করা হয়নি।

শক্তিশালী টাইপ সিস্টেমগুলি সহ সি ++ এবং অন্যান্য ভাষায় সীমা-সীমাবদ্ধ প্রকারের জন্য বিশেষ বৈশিষ্ট্যগুলির প্রয়োজন হয় না।

সি ++ তে আপনার লক্ষ্যগুলি তুলনামূলকভাবে কেবল ব্যবহারকারী-সংজ্ঞায়িত প্রকারের সাথে পূরণ করা যায় । এবং অ্যাপ্লিকেশনগুলিতে যেখানে পরিসীমা-সীমাবদ্ধ প্রকারগুলি কাঙ্ক্ষিত, সেগুলি খুব কমই যথেষ্ট । উদাহরণস্বরূপ, একটিও চাইবে যে সংস্থাপকটি শারীরিক ইউনিট গণনা সঠিকভাবে রচিত হয়েছিল তা যাচাই করুক, যাতে বেগ / সময় একটি ত্বরণ তৈরি করে এবং ত্বরণ / সময়ের বর্গমূল গ্রহণের ফলে বেগ তৈরি হয়। এটি সুবিধার্থে করার জন্য কোনও সূত্রে প্রদর্শিত হতে পারে এমন প্রতিটি প্রকারের স্পষ্টভাবে নামকরণ না করে প্রকারের একটি পদ্ধতি নির্ধারণের দক্ষতা প্রয়োজন। এটি সি ++ এ করা যেতে পারে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.