Quali svantaggi ci sono per l'ambito basato sulle condizioni?

1

Nello pseudo codice qui sotto, la chiave variabile deve essere dichiarata e inizializzata al di fuori del contesto che è usata / rilevante perché ci sono due se-blocchi disparati con la stessa identica condizione.

Stavo pensando che sarebbe bello se una lingua potesse considerare due se blocchi del genere avessero lo stesso scopo. Quali sono gli svantaggi, se ce ne sono, con questo approccio?

Prima :

class Foo
  static bool CacheEnabled = true
  static Foo Get(string name)
    Foo result
    string key = "cache_" + name
    if(CacheEnabled)
      if(Cache.GetFoo(key, out result))
        return result
    result = new Foo()
    //
    // rest of initialization here..
    //
    if(CacheEnabled)
      Cache.PutFoo(key, result)
    return result

Dopo

class Foo
  static bool CacheEnabled = true
  static Foo Get(string name)
    Foo result
    if(CacheEnabled)
      string key = "cache_" + name
      if(Cache.GetFoo(key, out result))
        return result
    result = new Foo()
    //
    // rest of initialization here..
    //
    if(CacheEnabled)
      Cache.PutFoo(key, result) // key is available since the condition is the same
    return result
    
posta Aaron Anodide 10.10.2014 - 22:51
fonte

3 risposte

6

Lo scope lessicale è una proprietà in fase di compilazione (in realtà, anche in fase di analisi). "La stessa condizione" è una proprietà di runtime. La comprensione delle proprietà di esecuzione al momento della compilazione è difficile . In effetti, è quasi sempre impossibile. Anche la più semplice, la più stupida possibile proprietà di runtime, vale a dire "questa esecuzione per sempre" (ovvero il problema di interruzione) è impossibile da capire in fase di compilazione.

Come risulta, la tua "stessa condizione" è fondamentalmente il problema dell'equivalenza della funzione, che, come il problema dell'arresto, è noto per essere indecidibile. IOW: è impossibile per il compilatore capire che i due blocchi hanno la stessa condizione.

Si noti, tuttavia, che tutto ciò si applica solo alle lingue complete di Turing. Se si limita ciò che i programmatori sono autorizzati a inserire in una condizione sufficiente, allora si potrebbe essere in grado di dimostrare al momento della compilazione che le due condizioni sono le stesse. Nota anche che ci vuole pochissimo per rendere un linguaggio Turing-completo, o in un altro modo: devi togliere molte funzioni da una lingua per rendere decidibile Function Equivalence.

Indipendentemente dal fatto che non valga la pena o meno di disabilitare in modo sostanziale le dichiarazioni se solo per salvare un'inizializzazione delle variabili è una questione di gusti, immagino.

    
risposta data 11.10.2014 - 00:43
fonte
3

Voterò no, perché la sua disponibilità tenderebbe a incoraggiare la duplicazione e mescolare i livelli di astrazione. Per il tuo esempio, stai mescolando il problema con il caching con il problema del calcolo e la duplicazione del condizionale. Entrambi questi problemi potrebbero essere mitigati spostando la chiave condizionale e la chiave alla classe Cache . Esistono altri costrutti linguistici, come le funzioni e i decoratori di prima classe, in grado di gestire questo tipo di caso d'uso in modo molto più pulito.

Potrebbero esserci altri casi d'uso che si adatterebbero meglio, ma non posso pensare a nessuno che non implichi la duplicazione del condizionale, e quindi non potrebbe essere gestito in modo più pulito con alcuni refactoring.

    
risposta data 10.10.2014 - 23:22
fonte
2

Come ha detto Jörg W Mittag, cercare di convincere dimostrare che due condizioni sono equivalenti è indecidibile. L'utente dovrebbe annotare quali condizioni sono equivalenti e cosa succede se annotano in modo errato?

Ciò renderebbe anche gli obiettivi molto più complicati da ragionare (e sicuramente anche più scoraggianti per i nuovi programmatori). Anche le variabili misteriose che entrano e escono dall'ambito possono essere un'altra fonte di bug.

Inoltre, ciò che si desidera potrebbe essere interamente usando le funzioni di prima classe:

class Foo
  static bool CacheEnabled = true

  static Foo Get(string name)
    Foo initializer() = () =>
      // the variable "key" is inaccessible here
      Foo result = new Foo()
      //
      // rest of initialization here..
      //
      return result

    Foo result
    string key = "cache_" + name
    if(CacheEnabled)
      if(Cache.GetFoo(key, out result))
        return result

    // call initializer
    result = initializer()

    if(CacheEnabled)
      Cache.PutFoo(key, result)
    return result
    
risposta data 11.10.2014 - 01:59
fonte

Leggi altre domande sui tag